• JWT中token的理解


    今天我们来聊一聊关于JWT授权的事情。

    JWT:Json Web Token。顾名思义,它是一种在Web中,使用Json来进行Token授权的方案。

    既然没有找好密码,token是如何解决信任问题的呢?

    解决信任问题,只需要解决两个问题即可:

    token是不是来自我信任的机构颁发

    token中的信息是否被篡改

    对于第一个问题而言,确认token确实是由被信任的第三方颁发的,一般都是通过加密算法来建立信任,颁发时使用密钥进行加密,如果能够对加密内容进行正常解密说明token来自信任方。常用的加密算法分为:

    对称可逆加密:使用同一个秘钥来加密解密,如果token能解密就能证明来源,秘钥不对外公开

    非对称可逆加密:使用一组秘钥对(私钥加密+公钥解密),如果token能使用公钥进行解密就能证明来源,公钥与私钥之间互相不可推算

     

    优缺点:

    对称可逆加密效率高,速度快,但是由于对称可逆加密使用的是同一个秘钥,所以必须向解密的应用提供秘钥,相对而言不安全,所以一般只用于内部应用之间。

    非对称可逆加密速度相对慢一些,但是加密时通过私钥加密而解密时只需要提供公钥即可,所以用于对外提供加密机制更加安全可靠,所以多用于向第三方提供加密服务时使用。

     

    算法举例:

    HS256
    HS256 (带有 SHA-256 的 HMAC 是一种对称算法, 双方之间仅共享一个 密钥。由于使用相同的密钥生成签名和验证签名, 因此必须注意确保密钥不被泄密。

    2 RS256
    RS256 (采用SHA-256 的 RSA 签名) 是一种非对称算法, 它使用公共/私钥对: 标识提供方采用私钥生成签名, JWT 的使用方获取公钥以验证签名。由于公钥 (与私钥相比) 不需要保护, 因此大多数标识提供方使其易于使用方获取和使用 (通常通过一个元数据URL)。

     

    JWT格式说明

    JWT令牌格式 作用
    Header 头     { "alg": "HS256", "typ": "JWT"}
    Payload 有效载荷 使用base64进行序列化,任何人都可以读到,所以不要包含敏感信息
    Signature 签名

    防止抵赖-防止篡改,一旦头和有效载荷有内容被篡改,则生成签名部分必将与原内容不同

    =HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

     

    JWT如何解决信任问题的呢?

    将签名部分使用秘钥进行解密,如果可以正常解开,说明令牌来自信任方颁发,将解密后的内容与JWT的头部和有效载荷的base64编码内容对比是否一致,如果一致,说明令牌未被篡改。也就解决了token信任的第二个问题。

     

    算法实现:

    下面是使用上述的两种加密算法生成的jwt

    HS256算法实现

    复制代码
     1 public string GetToken(UserInfoDTO userInfo)
     2 {
     3     string secretKey = _configuration["SercetKey"];
     4     var signingCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey)), SecurityAlgorithms.HmacSha256);
     5 
     6     var claims = new Claim[] {
     7         new Claim("id",userInfo.Id.ToString()),
     8         new Claim("age",userInfo.Age.ToString()),
     9         new Claim("name",userInfo.Name),
    10         new Claim("mobile",userInfo.Mobile),
    11         new Claim("email",userInfo.EMail),
    12         new Claim("role",userInfo.Role),
    13     };
    14 
    15     var token = new JwtSecurityToken(
    16         issuer: _configuration["Issuer"], //发行人
    17         audience: _configuration["Audience"], //受众人
    18         claims: claims,
    19         expires: DateTime.UtcNow.AddMinutes(2),//60分钟有效期
    20         notBefore: DateTime.UtcNow.AddMinutes(1),//1分钟后有效
    21         signingCredentials: signingCredentials);
    22     string returnToken = new JwtSecurityTokenHandler().WriteToken(token);
    23     return returnToken;
    24 }
    复制代码

    RSA256算法实现

    复制代码
     1 public string GetToken(UserInfoDTO userInfo)
     2 {
     3     string filepath = Directory.GetCurrentDirectory();
     4     RSAParameters rSAParameter = default(RSAParameters);
     5     //没有生成过私钥文件,就创建,否则读取私钥
     6     if (!File.Exists(Path.Combine(filepath, "key.private.json")))
     7     {
     8         rSAParameter = GenerateAndSaveKey(filepath);
     9     }
    10     else
    11     {
    12         rSAParameter = JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine(filepath, "key.private.json")));
    13     }
    14 
    15     var signingCredentials = new SigningCredentials(new RsaSecurityKey(rSAParameter), SecurityAlgorithms.RsaSha256);
    16     var claims = new Claim[] {
    17         new Claim("id",userInfo.Id.ToString()),
    18         new Claim("age",userInfo.Age.ToString()),
    19         new Claim("name",userInfo.Name),
    20         new Claim("mobile",userInfo.Mobile),
    21         new Claim("email",userInfo.EMail),
    22         new Claim("role",userInfo.Role),
    23     };
    24 
    25     var token = new JwtSecurityToken(
    26         issuer: _configuration["Issuer"], //发行人
    27         audience: _configuration["Audience"], //受众人
    28         claims: claims,
    29         expires: DateTime.UtcNow.AddMinutes(60),//60分钟有效期
    30         notBefore: DateTime.UtcNow.AddMinutes(1),//1分钟后有效
    31         signingCredentials: signingCredentials);
    32     string returnToken = new JwtSecurityTokenHandler().WriteToken(token);
    33     return returnToken;
    34 }
    复制代码

    在postman中请求:

     

     

    将返回的jwt拿到jwt官网解析即可看到已经包含了我们需要传递的内容。因为jwt中传递的内容可以被看到,所以一定不要传递类似密码这类敏感信息

     

    创建一个webapi项目,作为受保护的资源,开启权限认证,并使用jwt作为鉴权方式

    复制代码
     1 services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
     2 .AddJwtBearer(configureOptions =>
     3 {
     4     configureOptions.TokenValidationParameters = new TokenValidationParameters
     5     {
     6         ValidAudience = Configuration["Audience"],
     7         ValidateAudience = true,
     8         ValidIssuer = Configuration["Issuer"],
     9         ValidateIssuer = true,
    10         ValidateLifetime = false,
    11         LifetimeValidator = (notBefore, expires, securityToken, validationParameters) => {
    12             DateTime now = DateTime.UtcNow;
    13             if (now.CompareTo(notBefore) < 0 || now.CompareTo(expires) > 0)
    14                 return false;
    15             return true;
    16         },
    17         IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["SercetKey"])), //对称加密方式,获取密钥
    18         //IssuerSigningKey = new RsaSecurityKey(GetPulicKey()), //非对称加密方式,获取第三方提供的公钥
    19         ValidateIssuerSigningKey = true,
    20          
    21     };
    22 });
    复制代码

    不传递token请求受保护的api,则会返回401

     

     

    加上获取的token,则可以正常请求

     

    项目源码链接: https://pan.baidu.com/s/1u9Lu7rLq7swSXOdV_sNh-g?pwd=mxfg

     

  • 相关阅读:
    两数之和-第13届蓝桥杯选拔赛Python真题精选
    超详细!linux系统nlg-eval安装指南
    深度学习人脸表情识别算法 - opencv python 机器视觉 计算机竞赛
    docker快速安装redis,mysql,minio,nacos等常用软件【持续更新】
    pycharm关于第三方库操作大全
    OpenGL 坐标投影与反投影(Qt)
    Center-based 3D Object Detection and Tracking
    20221106 今天的世界发生了什么
    设计模式---工厂模式
    go实现优先级channel
  • 原文地址:https://www.cnblogs.com/XFlyMan/p/16482674.html