zoukankan      html  css  js  c++  java
  • JWT-生成、校验、解析Token(C#)

    重要对象:

    JwtSecurityToken:代表一个jwt token,可以直接用此对象生成token字符串,也可以使用token字符串创建此对象
    
    SecurityToken:JwtSecurityToken的基类,包含基础数据

    JwtSecurityTokenHandler:创建、校验token,返回ClaimsPrincipal
      CanReadToken():确定字符串是否是格式良好的Json Web令牌(JWT)
      ReadJwtToken(string token):token字符串转为JwtSecurityToken对象
      ValidateToken(string token、TokenValidationParameters parameter,out SecurityToken validatedToken):校验token,返回ClaimsIdentity,

      

    方式1:

    引用NuGet包:System.IdentityModel.Tokens.Jwt

    static void Main(string[] args)
            {
                //引用System.IdentityModel.Tokens.Jwt
                DateTime utcNow = DateTime.UtcNow;
                string key = "f47b558d-7654-458c-99f2-13b190ef0199";
                SecurityKey securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(key));
    
                var claims = new List<Claim>() {
                    new Claim("ID","1"),
                    new Claim("Name","fan")
                };
                JwtSecurityToken jwtToken = new JwtSecurityToken(
                    issuer: "fan",
                    audience: "audi~~!",
                    claims: claims,
                    notBefore: utcNow,
                    expires: utcNow.AddYears(1),
                    signingCredentials: new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256)
                    );
    
                //生成token方式1
                string token1 = new JwtSecurityTokenHandler().WriteToken(jwtToken);
                //A Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor that contains details of contents of the token.
    
                var tokenDescriptor = new SecurityTokenDescriptor // 创建一个 Token 的原始对象
                {
                    Issuer = "fan",
                    Audience = "audi",
                    Subject = new ClaimsIdentity(new[]
                           {
                                new Claim(ClaimTypes.Name, "")
                            }),
                    Expires = DateTime.Now.AddMinutes(60),
                    SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(key)), SecurityAlgorithms.HmacSha256)
                };
                //生成token方式2
                SecurityToken securityToken = new JwtSecurityTokenHandler().CreateToken(tokenDescriptor);
                var token2 = new JwtSecurityTokenHandler().WriteToken(securityToken);
    
                //校验token
                var validateParameter = new TokenValidationParameters()
                {
                    ValidateLifetime = true,
                    ValidateAudience = true,
                    ValidateIssuer = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = "fan",
                    ValidAudience = "audi~~!",
                    IssuerSigningKey = securityKey,
                };
                //不校验,直接解析token
                //jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(token1);
                try
                {
                    //校验并解析token
                    var claimsPrincipal = new JwtSecurityTokenHandler().ValidateToken(token1, validateParameter, out SecurityToken validatedToken);//validatedToken:解密后的对象
                   var jwtPayload = ((JwtSecurityToken)validatedToken).Payload.SerializeToJson(); //获取payload中的数据 
                    
                }
                catch (SecurityTokenExpiredException)
                {
                    //表示过期
                }
                catch (SecurityTokenException)
                {
                    //表示token错误
                }
            }

    方式2:

    引用Nuget包:JWT 

           /// <summary>
            /// 创建token
            /// </summary>
            /// <returns></returns>
            public static string CreateJwtToken(IDictionary<string, object> payload, string secret, IDictionary<string, object> extraHeaders = null)
            {
                IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
                IJsonSerializer serializer = new JsonNetSerializer();
                IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
                var token = encoder.Encode(payload, secret);
                return token;
            }
            /// <summary>
            /// 校验解析token
            /// </summary>
            /// <returns></returns>
            public static string ValidateJwtToken(string token, string secret)
            {
                try
                {
                    IJsonSerializer serializer = new JsonNetSerializer();
                    IDateTimeProvider provider = new UtcDateTimeProvider();
                    IJwtValidator validator = new JwtValidator(serializer, provider);
                    IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                    IJwtAlgorithm alg = new HMACSHA256Algorithm();
                    IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, alg);
                    var json = decoder.Decode(token, secret, true);
                    //校验通过,返回解密后的字符串
                    return json;
                }
                catch (TokenExpiredException)
                {
                    //表示过期
                    return "expired";
                }
                catch (SignatureVerificationException)
                {
                    //表示验证不通过
                    return "invalid";
                }
                catch (Exception)
                {
                    return "error";
                }
            }
    
    
    //-------------客户端调用---------------
    public static void Main(string[] args)
            {
                var sign = "123";
                var extraHeaders = new Dictionary<string, object>
                         {
                                              { "myName", "limaru" },
                        };
                //过期时间(可以不设置,下面表示签名后 10秒过期)
                double exp = (DateTime.UtcNow.AddSeconds(10) - new DateTime(1970, 1, 1)).TotalSeconds;
                var payload = new Dictionary<string, object>
                         {
                                             { "userId", "001" },
                             { "userAccount", "fan" },
                             { "exp",exp }
                                         };
                var token = CreateJwtToken(payload, sign, extraHeaders);
                var text = ValidateJwtToken(token, sign);
                Console.ReadKey();
            }

    方式3:

    手写jwt算法:

    JWT组成
    
      样式:"xxxxxxxxxxxx.xxxxxxxxxxxxx.xxxxxxxxxxxxxxxx"由三部分组成.
    
    (1).Header头部:{"alg":"HS256","typ":"JWT"}基本组成,也可以自己添加别的内容,然后对最后的内容进行Base64编码.
    
    (2).Payload负载:iss、sub、aud、exp、nbf、iat、jti基本参数,也可以自己添加别的内容,然后对最后的内容进行Base64编码.
    
    (3).Signature签名:将Base64后的Header和Payload通过.组合起来,然后利用Hmacsha256+密钥进行加密。
    
    #region Base64编码
     2         /// <summary>
     3         /// Base64编码
     4         /// </summary>
     5         /// <param name="text">待编码的文本字符串</param>
     6         /// <returns>编码的文本字符串</returns>
     7         public string Base64UrlEncode(string text)
     8         {
     9             var plainTextBytes = Encoding.UTF8.GetBytes(text);
    10             var base64 = Convert.ToBase64String(plainTextBytes).Replace('+', '-').Replace('/', '_').TrimEnd('=');
    11             return base64;
    12         }
    13         #endregion
    14 
    15         #region Base64解码
    16         /// <summary>
    17         /// Base64解码
    18         /// </summary>
    19         /// <param name="base64UrlStr"></param>
    20         /// <returns></returns>
    21 
    22         public string Base64UrlDecode(string base64UrlStr)
    23         {
    24             base64UrlStr = base64UrlStr.Replace('-', '+').Replace('_', '/');
    25             switch (base64UrlStr.Length % 4)
    26             {
    27                 case 2:
    28                     base64UrlStr += "==";
    29                     break;
    30                 case 3:
    31                     base64UrlStr += "=";
    32                     break;
    33             }
    34             var bytes = Convert.FromBase64String(base64UrlStr);
    35             return Encoding.UTF8.GetString(bytes);
    36         }
    #endregion Base64编码和解码
    
    /// <summary>
            /// 手写JWT算法
            /// </summary>
            public bool TestJwt1()
            {
                string secretKey = Configuration["SecretKey"];
                //1.加密
                //1.1 表头的处理
                string headerBase64Url = this.Base64UrlEncode("{"alg":"HS256","typ":"JWT"}");
                //1.2 PayLoad的处理
                var jwtPayLoad = new
                {
                    expire = DateTime.Now.AddMinutes(15),
                    userId = "00000000001",
                    userAccount = "admin"
                };
                string payloadBase64Url = this.Base64UrlEncode(JsonConvert.SerializeObject(jwtPayLoad));
                //1.3 Sign的处理
                string sign = $"{headerBase64Url}.{payloadBase64Url}".HMACSHA256(secretKey);
                //1.4 最终的jwt字符串
                string jwtStr = $"{headerBase64Url}.{payloadBase64Url}.{sign}";
    
                //2.校验token是否正确
                bool result;   //True表示通过,False表示未通过
                //2.1. 获取token中的PayLoad中的值,并做过期校验
                JwtData myData = JsonConvert.DeserializeObject<JwtData>(this.Base64UrlDecode(jwtStr.Split('.')[1]));  //这一步已经获取到了payload中的值,并进行转换了
                var nowTime = DateTime.Now;
                if (nowTime > myData.expire)
                {
                    //表示token过期,校验未通过
                    result = false;
                    return result;
                }
                else
                {
                    //2.2 做准确性校验
                    var items = jwtStr.Split('.');
                    var oldSign = items[2];
                    string newSign = $"{items[0]}.{items[1]}".HMACSHA256(secretKey);
                    result = oldSign == newSign;  //true表示检验通过,false表示检验未通过
                    return result;
                }
            }
    View Code

     

    参考:

    https://www.cnblogs.com/ye-hcj/articles/8151385.html

    https://www.cnblogs.com/yaopengfei/p/12162507.html

  • 相关阅读:
    3D Computer Grapihcs Using OpenGL
    3D Computer Grapihcs Using OpenGL
    3D Computer Grapihcs Using OpenGL
    3D Computer Grapihcs Using OpenGL
    转:RealThinClient LinkedObjects Demo解析
    转:RealThinClient (RTC)是什么?
    DataSanp的控制老大-DSServer
    5.Firedac错误信息
    4.FireDAC组件快照 二
    3.FireDAC组件快照
  • 原文地址:https://www.cnblogs.com/fanfan-90/p/12911203.html
Copyright © 2011-2022 走看看