AuthenticationMiddleware.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. using ERP.Framework.Cache;
  2. using ERP.Framework.Config;
  3. using ERP.Framework.Constants;
  4. using ERP.Framework.Security;
  5. using ERP.Framework.Utils;
  6. using ERP.Framework.WebApi;
  7. using Microsoft.AspNetCore.Builder;
  8. using Microsoft.AspNetCore.Http;
  9. using Microsoft.Extensions.Configuration;
  10. using Newtonsoft.Json;
  11. using System.IdentityModel.Tokens.Jwt;
  12. using System.Net;
  13. using System.Security.Claims;
  14. namespace ERP.Framework.Middleware
  15. {
  16. /// <summary>
  17. /// 验证 (解签 header附带用户id) useJwt
  18. /// </summary>
  19. public class AuthenticationMiddleware : IMiddleware
  20. {
  21. private readonly IConfiguration _configuration;
  22. public AuthenticationMiddleware(IConfiguration configuration)
  23. {
  24. this._configuration = configuration;
  25. }
  26. public async Task InvokeAsync(HttpContext context, RequestDelegate next)
  27. {
  28. var path = context.Request.Path.ToString();
  29. var securityConfig = _configuration.GetSection(FrameworkConstant.SECURITY_CONFIG).Get<SecurityConfig>() ?? new SecurityConfig();
  30. {
  31. if (securityConfig.WhiteList != null && securityConfig.WhiteList.Any(w => UrlUtil.Match(w, path)))
  32. await next(context);
  33. return;
  34. }
  35. var token = context.Request.Headers[AuthConstant.HEADER].ToString().Replace(FrameworkConstant.TOKEN_PREFIX, "").TrimStart();
  36. var isValid = TokenHelper.ValidateToken(token, securityConfig.JwtSecurityKey);
  37. if (!isValid)
  38. {
  39. // 返回401状态码和自定义错误信息
  40. context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
  41. context.Response.ContentType = "application/json";
  42. var errorJson = JsonConvert.SerializeObject(new Result()
  43. {
  44. Code = 1000001,
  45. //Message = AuthI18N.TokenValidate
  46. });
  47. await context.Response.WriteAsync(errorJson);
  48. return;
  49. }
  50. var claims = TokenHelper.GetClaims(token);
  51. var tokenId = claims.FirstOrDefault(t => t.Type == JwtRegisteredClaimNames.UniqueName)!.Value;
  52. var userId = claims.FirstOrDefault(t => t.Type == JwtRegisteredClaimNames.NameId)!.Value;
  53. //var userName = claims.FirstOrDefault(t => t.Type == ClaimTypes.Name)!.Value;
  54. var checkLastActivityResult = CheckLastActivity(tokenId, securityConfig.ActivityTimeOut);
  55. if (checkLastActivityResult != null)
  56. {
  57. context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
  58. context.Response.ContentType = "application/json";
  59. await context.Response.WriteAsync(JsonConvert.SerializeObject(checkLastActivityResult));
  60. return;
  61. }
  62. context.Items["TokenId"] = tokenId;
  63. context.Items["UserID"] = userId;
  64. await next(context);
  65. return;
  66. }
  67. private static Result CheckLastActivity(string tokenId, int activityTimeOut)
  68. {
  69. DateTime date;
  70. var result = new Result();
  71. var key = AuthConstant.LAST_ACTIVITY + tokenId;
  72. var lastActivity = RedisHelper.GetWithExpire(key);
  73. var value = lastActivity.Value.ToString();
  74. var expireTime = lastActivity.Expiry;
  75. if (value.IsNullOrEmpty())
  76. {
  77. result.Code = 1000001;
  78. //result.Message = AuthI18N.TokenValidate;
  79. return result;
  80. }
  81. if (value == "-1")
  82. {
  83. result.Code = 1000002;
  84. //result.Message = AuthI18N.KickedOut;
  85. return result;
  86. }
  87. if (value == "-2")
  88. {
  89. result.Code = 1000003;
  90. //result.Message = AuthI18N.ConcurrentLogin;
  91. return result;
  92. }
  93. if (DateTime.TryParse(value, out date))
  94. {
  95. var isOnline = DateTime.Now <= date;
  96. if (isOnline)
  97. {
  98. SetLastActivityCache(tokenId, activityTimeOut, expireTime);
  99. }
  100. else
  101. {
  102. result.Code = 1000004;
  103. //result.Message = AuthI18N.IdleTimeOut;
  104. return result;
  105. }
  106. }
  107. return null;
  108. }
  109. /// <summary>
  110. /// 刷新last Activity
  111. /// </summary>
  112. /// <param name="tokenId"></param>
  113. /// <param name="activityTimeOut"></param>
  114. private static void SetLastActivityCache(
  115. string tokenId
  116. , int activityTimeOut
  117. , TimeSpan? expireTime)
  118. {
  119. var key = AuthConstant.LAST_ACTIVITY + tokenId;
  120. var val = DateTime.Now.AddMinutes(activityTimeOut).ToDateLongString();
  121. RedisHelper.SaveExpire(key, val, expireTime);
  122. }
  123. }
  124. public static class AuthenticationMiddlewareExtensions
  125. {
  126. public static IApplicationBuilder UseAuthenticationMiddleware(this IApplicationBuilder builder)
  127. {
  128. return builder.UseMiddleware<AuthenticationMiddleware>();
  129. }
  130. }
  131. }