You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
6.4 KiB

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);
}
/// <summary>
/// Token是否是符合要求的标准 Json Web 令牌
/// </summary>
/// <param name="tokenStr"></param>
/// <returns></returns>
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;
}
}
/// <summary>
/// 从Token解密出JwtSecurityToken,JwtSecurityToken : SecurityToken
/// </summary>
/// <param name="tokenStr"></param>
/// <returns></returns>
public JwtSecurityToken GetJwtSecurityToken(string tokenStr)
{
var jwt = _jwtSecurityTokenHandler.ReadJwtToken(tokenStr);
return jwt;
}
/// <summary>
/// 判断token是否过期
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
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;
}
}
}