|
|
@@ -0,0 +1,113 @@
|
|
|
+using Microsoft.IdentityModel.Tokens;
|
|
|
+
|
|
|
+using System.IdentityModel.Tokens.Jwt;
|
|
|
+using System.Security.Claims;
|
|
|
+
|
|
|
+namespace VberZero.Jwt
|
|
|
+{
|
|
|
+ public static class JwtHelper
|
|
|
+ {
|
|
|
+ public static string CreateAccessToken(ClaimsIdentity identity, TokenAuthConfiguration configuration, TimeSpan? expiration = null)
|
|
|
+ {
|
|
|
+ return CreateAccessToken(CreateJwtClaims(identity), configuration, expiration);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static string CreateAccessToken(IEnumerable<Claim> claims, TokenAuthConfiguration configuration, TimeSpan? expiration = null)
|
|
|
+ {
|
|
|
+ var now = DateTime.UtcNow;
|
|
|
+
|
|
|
+ var jwtSecurityToken = new JwtSecurityToken(
|
|
|
+ issuer: configuration.Issuer,
|
|
|
+ audience: configuration.Audience,
|
|
|
+ claims: claims,
|
|
|
+ notBefore: now,
|
|
|
+ expires: now.Add(expiration ?? configuration.Expiration),
|
|
|
+ signingCredentials: configuration.SigningCredentials
|
|
|
+ );
|
|
|
+
|
|
|
+ return new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static List<Claim> CreateJwtClaims(ClaimsIdentity identity)
|
|
|
+ {
|
|
|
+ var claims = identity.Claims.ToList();
|
|
|
+ var nameIdClaim = claims.First(c => c.Type == ClaimTypes.NameIdentifier);
|
|
|
+
|
|
|
+ // Specifically add the jti (random nonce), iat (issued timestamp), and sub (subject/user) claims.
|
|
|
+ claims.AddRange(new[]
|
|
|
+ {
|
|
|
+ new Claim(JwtRegisteredClaimNames.Sub, nameIdClaim.Value),
|
|
|
+ new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
|
|
|
+ new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.Now.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64)
|
|
|
+ });
|
|
|
+
|
|
|
+ return claims;
|
|
|
+ }
|
|
|
+
|
|
|
+ //public static ClaimsPrincipal ReadJwtToken(string token)
|
|
|
+ //{
|
|
|
+ // var validateParameter = new TokenValidationParameters()
|
|
|
+ // {
|
|
|
+ // ValidateLifetime = false,
|
|
|
+ // ValidateAudience = false,
|
|
|
+ // ValidateIssuer = false,
|
|
|
+ // ValidateIssuerSigningKey = false,
|
|
|
+ // };
|
|
|
+ // ClaimsPrincipal principal =
|
|
|
+ // new JwtSecurityTokenHandler().ValidateToken(token, validateParameter, out var securityToken);
|
|
|
+ // return principal;
|
|
|
+ //}
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 校验token
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="token"></param>
|
|
|
+ /// <param name="configuration"></param>
|
|
|
+ /// <param name="principal"></param>
|
|
|
+ /// <param name="jwtPayload"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static bool VerifyJwtToken(string token, TokenAuthConfiguration configuration, out ClaimsPrincipal principal, out string jwtPayload)
|
|
|
+ {
|
|
|
+ principal = null;
|
|
|
+ jwtPayload = null;
|
|
|
+ //校验token
|
|
|
+ var validateParameter = new TokenValidationParameters()
|
|
|
+ {
|
|
|
+ ValidateLifetime = true,
|
|
|
+ ValidateAudience = true,
|
|
|
+ ValidateIssuer = true,
|
|
|
+ ValidateIssuerSigningKey = true,
|
|
|
+ ValidIssuer = configuration.Issuer,
|
|
|
+ ValidAudience = configuration.Audience,
|
|
|
+ IssuerSigningKey = configuration.SecurityKey,
|
|
|
+ ClockSkew = TimeSpan.Zero//校验过期时间必须加此属性
|
|
|
+ };
|
|
|
+ //不校验,直接解析token
|
|
|
+ //jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(token1);
|
|
|
+ bool success;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ //校验并解析token,validatedToken是解密后的对象
|
|
|
+ principal = new JwtSecurityTokenHandler().ValidateToken(token, validateParameter, out SecurityToken validatedToken);
|
|
|
+ //获取payload中的数据
|
|
|
+ jwtPayload = ((JwtSecurityToken)validatedToken).Payload.SerializeToJson();
|
|
|
+ success = true;
|
|
|
+ }
|
|
|
+ catch (SecurityTokenExpiredException ex)
|
|
|
+ {
|
|
|
+ //表示过期
|
|
|
+ success = false;
|
|
|
+ }
|
|
|
+ catch (SecurityTokenException ex)
|
|
|
+ {
|
|
|
+ //表示token错误
|
|
|
+ success = false;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ success = false;
|
|
|
+ }
|
|
|
+ return success;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|