using System; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; using Newtonsoft.Json; using QualityControlPlatform.Helpers.Response; using static QualityControlPlatform.Helpers.Response.ResponseHelper; namespace QualityControlPlatform.Middleware { public class JwtMiddleware { private readonly RequestDelegate _next; private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler = new JwtSecurityTokenHandler(); private static IConfiguration Configuration { get; set; } public JwtMiddleware(RequestDelegate next, IConfiguration config) { _next = next; Configuration = config; } public async Task Invoke(HttpContext context) { if (context == null) throw new ArgumentNullException(nameof(context)); var tokenStr = context.Request.Headers["Authorization"].ToString(); //未携带token请求不需要授权页面,让其直接通过,用方法名上面的校验来判断 if (!string.IsNullOrEmpty(tokenStr)) { //携带了token,判断token,回传失效,过期,或者续期 var setting = new JsonSerializerSettings { ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() }; //token 是否合规 if (!IsCanReadToken(ref tokenStr)) { var result = new ResultModel() { Message = "invalid token", Code = Convert.ToInt32(ErrorEnum.TokenError) }; await context.Response.WriteAsync( JsonConvert.SerializeObject(result, setting), Encoding.UTF8); return; } // token是否超过有效期 if (IsExp(tokenStr)) { var result = new ResultModel() { Message = "token expired", Code = Convert.ToInt32(ErrorEnum.TokenError) }; await context.Response.WriteAsync( JsonConvert.SerializeObject(result, setting), Encoding.UTF8); return; } var claims = new[] { new Claim("userCode",GetJwtSecurityToken(tokenStr)?.Claims.FirstOrDefault(p=>p.Type.Equals("userCode"))?.Value) , new Claim("userName",GetJwtSecurityToken(tokenStr)?.Claims.FirstOrDefault(p=>p.Type.Equals("userName"))?.Value), new Claim("deptCode",GetJwtSecurityToken(tokenStr)?.Claims.FirstOrDefault(p=>p.Type.Equals("deptCode"))?.Value) , new Claim("deptName",GetJwtSecurityToken(tokenStr)?.Claims.FirstOrDefault(p=>p.Type.Equals("deptName"))?.Value) }; // 获取SecurityKey var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetSection("Authentication")["SecurityKey"])); var token = new JwtSecurityToken( issuer: Configuration.GetSection("Authentication")["IsSure"], // 发布者 audience: Configuration.GetSection("Authentication")["Audience"], // 接收者 notBefore: DateTime.Now, // token签发时间 expires: DateTime.Now.AddMinutes(30), // token过期时间 claims: claims, // 该token内存储的自定义字段信息 signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256) // 用于签发token的秘钥算法 ); // 返回成功信息,写出token var data = new JwtSecurityTokenHandler().WriteToken(token); context.Response.Headers.Add("newToken", data); } await _next(context); } /// /// Token是否是符合要求的标准 Json Web 令牌 /// /// /// public bool IsCanReadToken(ref string tokenStr) { tokenStr = tokenStr.Replace("Bearer ", string.Empty); var key = Encoding.UTF8.GetBytes(Configuration.GetSection("Authentication")["SecurityKey"]); var tokenValidationParameters = new TokenValidationParameters { ValidIssuer = Configuration.GetSection("Authentication")["IsSure"], ValidAudience = Configuration.GetSection("Authentication")["Audience"], IssuerSigningKey = new SymmetricSecurityKey(key), RequireExpirationTime = true, ClockSkew = TimeSpan.Zero }; // 验证token是否有效,如果过期,报错SecurityTokenExpiredException // 报错信息:IDX10223 : Lifetime validation failed try { var principal = _jwtSecurityTokenHandler.ValidateToken(tokenStr, tokenValidationParameters, out var securityToken); return principal != null; } catch (Exception) { return false; } } /// /// 从Token解密出JwtSecurityToken,JwtSecurityToken : SecurityToken /// /// /// public JwtSecurityToken GetJwtSecurityToken(string tokenStr) { var jwt = _jwtSecurityTokenHandler.ReadJwtToken(tokenStr); return jwt; } /// /// 判断token是否过期 /// /// /// public bool IsExp(string token) { return GetDateTime(Convert.ToDouble(GetJwtSecurityToken(token)?.Claims.First(c => c.Type == JwtRegisteredClaimNames.Exp)?.Value)) < DateTime.Now; } private static DateTime GetDateTime(double timeStamp)// 时间戳Timestamp转换成日期 { var dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); dateTime = dateTime.AddSeconds(timeStamp).ToLocalTime(); return dateTime; } } }