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
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;
|
|
}
|
|
}
|
|
}
|
|
|