/// <summary> /// Jwt帮助类 /// </summary> public static class JwtHelper { private static JwtSettings settings; public static JwtSettings Settings { set { settings = value; } get { return settings; } } /// <summary> /// 生成token /// </summary> /// <param name="claims"></param> /// <returns></returns> public static string CreateToken(IEnumerable<Claim> claims) { SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(settings.SecurityKey)); //证书 SigningCredentials credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var securityToken = new JwtSecurityToken( issuer: settings.Issuer,//JWT的签发者 audience: settings.Audience,//接收JWT的一方 claims: claims,//自定义用户值 expires: DateTime.Now.AddMinutes(settings.ExpMinutes),//什么时候过期 signingCredentials: credentials //证书 ); var token = new JwtSecurityTokenHandler().WriteToken(securityToken); return token; } /// <summary> /// 生成Jwt /// </summary> /// <param name="userName"></param> /// <param name="roleName"></param> /// <param name="userId"></param> /// <returns></returns> public static string CreateToken(string userName, string roleId, string userId) { //声明claim var claims = new Claim[] { new Claim(JwtRegisteredClaimNames.Sub, userName), new Claim(JwtRegisteredClaimNames.Jti, userId), new Claim(JwtRegisteredClaimNames.Iat,DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString(), ClaimValueTypes.Integer64),//签发时间 new Claim(JwtRegisteredClaimNames.Nbf, DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString(), ClaimValueTypes.Integer64),//生效时间 new Claim(JwtRegisteredClaimNames.Exp,DateTimeOffset.Now.AddMinutes(settings.ExpMinutes).ToUnixTimeMilliseconds().ToString(), ClaimValueTypes.Integer64), //过期时间 new Claim(JwtRegisteredClaimNames.Iss, settings.Issuer), new Claim(JwtRegisteredClaimNames.Aud, settings.Audience), new Claim(ClaimTypes.Name, userName), new Claim(ClaimTypes.Role, roleId), new Claim(ClaimTypes.Sid, userId), }; return CreateToken(claims); } /// <summary> /// 刷新token /// </summary> /// <returns></returns> public static string RefreshToken(string oldToken) { var pl = GetPayload(oldToken); //声明claim var claims = new Claim[] { new Claim(JwtRegisteredClaimNames.Sub, pl?.UserName), new Claim(JwtRegisteredClaimNames.Jti, pl?.UserId), new Claim(JwtRegisteredClaimNames.Iat,DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString(), ClaimValueTypes.Integer64),//签发时间 new Claim(JwtRegisteredClaimNames.Nbf, DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString(), ClaimValueTypes.Integer64),//生效时间 new Claim(JwtRegisteredClaimNames.Exp, DateTimeOffset.Now.AddMinutes(settings.ExpMinutes).ToUnixTimeMilliseconds().ToString(), ClaimValueTypes.Integer64), //过期时间 new Claim(JwtRegisteredClaimNames.Iss, settings.Issuer), new Claim(JwtRegisteredClaimNames.Aud, settings.Audience), new Claim(ClaimTypes.Name, pl?.UserName), new Claim(ClaimTypes.Role, pl?.RoleId), new Claim(ClaimTypes.Sid, pl?.UserId) }; return IsExp(oldToken) ? CreateToken(claims) : null; } /// <summary> /// 从token中获取用户身份 /// </summary> /// <param name="token"></param> /// <returns></returns> public static IEnumerable<Claim> GetClaims(string token) { var handler = new JwtSecurityTokenHandler(); var securityToken = handler.ReadJwtToken(token); return securityToken?.Claims; } /// <summary> /// 从Token中获取用户身份 /// </summary> /// <param name="token"></param> /// <returns></returns> public static ClaimsPrincipal GetPrincipal(string token) { var handler = new JwtSecurityTokenHandler(); try { return handler.ValidateToken(token, new TokenValidationParameters { ValidateAudience = false, ValidateIssuer = false, ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(settings.SecurityKey)), ValidateLifetime = false }, out SecurityToken validatedToken); } catch (Exception) { return null; } } /// <summary> /// 校验Token /// </summary> /// <param name="token">token</param> /// <returns></returns> public static bool CheckToken(string token) { var principal = GetPrincipal(token); if (principal is null) { return false; } return true; } /// <summary> /// 获取Token中的载荷数据 /// </summary> /// <param name="token">token</param> /// <returns></returns> public static JwtPayload GetPayload(string token) { var jwtHandler = new JwtSecurityTokenHandler(); JwtSecurityToken securityToken = jwtHandler.ReadJwtToken(token); return new JwtPayload { UserId = securityToken.Id, UserName = securityToken.Payload[JwtRegisteredClaimNames.Sub]?.ToString(), RoleId = (securityToken.Payload[ClaimTypes.Role] ?? 0).ToString(), ExpTime = Convert.ToInt64(securityToken.Payload[JwtRegisteredClaimNames.Exp]) }; } /// <summary> /// 获取Token中的载荷数据 /// </summary> /// <typeparam name="T">泛型</typeparam> /// <param name="token">token</param> /// <returns></returns> public static T GetPayload<T>(string token) { var jwtHandler = new JwtSecurityTokenHandler(); JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(token); return JsonConvert.DeserializeObject<T>(jwtToken.Payload.SerializeToJson()); } /// <summary> /// 判断token是否过期 /// </summary> /// <param name="token"></param> /// <returns></returns> public static bool IsExp(string token) { return Convert.ToDateTime(GetPrincipal(token)?.Claims.First(c => c.Type == JwtRegisteredClaimNames.Exp)?.Value) < DateTime.Now; //return GetPayload(token).ExpTime < DateTime.Now; } #region 从上下文请求流操作 /// <summary> /// 判断是否为AJAX请求 /// </summary> /// <param name="req"></param> /// <returns></returns> public static bool IsAjaxRequest(HttpRequest req) { bool result = false; var xreq = req.Headers.ContainsKey("x-requested-with"); if (xreq) { result = req.Headers["x-requested-with"] == "XMLHttpRequest"; } return result; } /// <summary> /// 获取Token /// </summary> /// <param name="req">请求流</param> /// <returns></returns> public static string GetToken(HttpRequest req) { string tokenHeader = req.Headers["Authorization"].ToString(); if (string.IsNullOrEmpty(tokenHeader)) throw new Exception("缺少token!"); string pattern = "^Bearer (.*?)$"; if (!Regex.IsMatch(tokenHeader, pattern)) throw new Exception("token格式不对!格式为:Bearer {token}"); string token = Regex.Match(tokenHeader, pattern).Groups[1]?.ToString(); if (string.IsNullOrEmpty(token)) throw new Exception("token不能为空!"); return token; } #endregion } //iss: jwt签发者 //sub: jwt所面向的用户 //aud: 接收jwt的一方 //exp: jwt的过期时间,这个过期时间必须要大于签发时间 //nbf: 定义在什么时间之前,该jwt都是不可用的. //iat: jwt的签发时间 //jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。 //var jwt_id = User.Claims.FirstOrDefault(p => p.Type == "jti").Value; //User.Claims.Select(p => new { p.Type, p.Value /// <summary> /// Jwt设置 /// </summary> public class JwtSettings { /// <summary> /// 发行人 /// </summary> public string Issuer { get; set; } /// <summary> /// 订阅者 /// </summary> public string Audience { get; set; } /// <summary> /// 加密key /// </summary> public string SecurityKey { get; set; } /// <summary> /// 过期分钟 /// </summary> public int ExpMinutes { get; set; } } /// <summary> /// Jwt载荷信息 /// </summary> public class JwtPayload { public string UserId { get; set; } public string UserName { get; set; } public string RealName { get; set; } public string RoleId { get; set; } public long ExpTime { get; set; } }
版权归属:
管理员
许可协议:
本文使用《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》协议授权
评论区