123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- using ERP.Framework.Cache;
- using ERP.Framework.Config;
- using ERP.Framework.Constants;
- using ERP.Framework.Exceptions;
- using ERP.Framework.Resource;
- using ERP.Framework.Security;
- using ERP.Framework.Utils;
- using ERP.Framework.WebApi;
- using Microsoft.AspNetCore.Builder;
- using Microsoft.AspNetCore.Http;
- using Microsoft.Extensions.Configuration;
- using Newtonsoft.Json;
- using System.IdentityModel.Tokens.Jwt;
- using System.Net;
- using System.Security.Claims;
- namespace ERP.Framework.Middleware
- {
- /// <summary>
- /// 验证 (解签 header附带用户id) useJwt
- /// </summary>
- public class AuthenticationMiddleware : IMiddleware
- {
- private readonly IConfiguration _configuration;
- public AuthenticationMiddleware(IConfiguration configuration)
- {
- this._configuration = configuration;
- }
- public async Task InvokeAsync(HttpContext context, RequestDelegate next)
- {
- var path = context.Request.Path.ToString();
- var securityConfig = _configuration.GetSection(FrameworkConstant.SECURITY_CONFIG).Get<SecurityConfig>() ?? new SecurityConfig();
- if (securityConfig.WhiteList != null && UrlUtil.Match(path, securityConfig.WhiteList))
- {
- await next(context);
- return;
- }
- var token = context.Request.Headers[AuthConstant.HEADER].ToString().Replace(FrameworkConstant.TOKEN_PREFIX, "").TrimStart();
- var isValid = TokenHelper.ValidateToken(token, securityConfig.JwtSecurityKey);
- if (!isValid)
- {
- // 返回401状态码和自定义错误信息
- context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
- context.Response.ContentType = "application/json";
- var errorJson = JsonConvert.SerializeObject(new Result()
- {
- Code = ErrorCode.TOKEN_VALIDATE,
- Message = FrameworkI18N.TokenValidate!
- });
- await context.Response.WriteAsync(errorJson);
- return;
- }
- var claims = TokenHelper.GetClaims(token);
- var tokenId = claims.FirstOrDefault(t => t.Type == JwtRegisteredClaimNames.UniqueName)!.Value;
- var userId = claims.FirstOrDefault(t => t.Type == JwtRegisteredClaimNames.NameId)!.Value;
- var userName = claims.FirstOrDefault(t => t.Type == ClaimTypes.Name)!.Value;
- var checkLastActivityResult = CheckLastActivity(tokenId, securityConfig.ActivityTimeOut);
- if (checkLastActivityResult != null)
- {
- context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
- context.Response.ContentType = "application/json";
- await context.Response.WriteAsync(JsonConvert.SerializeObject(checkLastActivityResult));
- return;
- }
- context.Items["TokenId"] = tokenId;
- context.Items["UserId"] = userId;
- context.Items["UserName"] = userName;
- await next(context);
- return;
- }
- private static Result? CheckLastActivity(string tokenId, int activityTimeOut)
- {
- DateTime date;
- var result = new Result();
- var key = AuthConstant.LAST_ACTIVITY + tokenId;
- var lastActivity = RedisHelper.GetWithExpire(key);
- var value = lastActivity.Value.ToString();
- var expireTime = lastActivity.Expiry;
- if (value.IsNullOrEmpty())
- {
- result.Code = ErrorCode.IDLE_TIME_OUT;
- result.Message = FrameworkI18N.IdleTimeOut!;
- return result;
- }
- if (value == "-1")
- {
- result.Code = ErrorCode.KICKED_OUT;
- result.Message = FrameworkI18N.KickedOut!;
- return result;
- }
- if (value == "-2")
- {
- result.Code = ErrorCode.CONCURRENT_LOGIN;
- result.Message = FrameworkI18N.ConcurrentLogin!;
- return result;
- }
- if (DateTime.TryParse(value, out date))
- {
- var isOnline = DateTime.Now <= date;
- if (isOnline)
- {
- SetLastActivityCache(tokenId, activityTimeOut, expireTime);
- }
- else
- {
- result.Code = ErrorCode.IDLE_TIME_OUT;
- result.Message = FrameworkI18N.IdleTimeOut!;
- return result;
- }
- }
- return null;
- }
- /// <summary>
- /// 刷新last Activity
- /// </summary>
- /// <param name="tokenId"></param>
- /// <param name="activityTimeOut"></param>
- private static void SetLastActivityCache(
- string tokenId
- , int activityTimeOut
- , TimeSpan? expireTime)
- {
- var key = AuthConstant.LAST_ACTIVITY + tokenId;
- var val = DateTime.Now.AddMinutes(activityTimeOut).ToDateLongString();
- RedisHelper.SaveExpire(key, val, expireTime);
- }
- }
- public static class AuthenticationMiddlewareExtensions
- {
- public static IApplicationBuilder UseAuthenticationMiddleware(this IApplicationBuilder builder)
- {
- return builder.UseMiddleware<AuthenticationMiddleware>();
- }
- }
- }
|