平安校园
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.

JwtHandler.cs 5.1 KiB

4 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. 
  2. //
  3. using MoYu.Authorization;
  4. using MoYu.DataEncryption;
  5. using MoYu.Logging.Extensions;
  6. using System.Security.Claims;
  7. namespace SafeCampus.Web.Core;
  8. public class JwtHandler : AppAuthorizeHandler
  9. {
  10. /// <summary>
  11. /// 重写 Handler 添加自动刷新
  12. /// </summary>
  13. /// <param name="context"></param>
  14. /// <param name="httpContext"></param>
  15. /// <returns></returns>
  16. public override async Task HandleAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
  17. {
  18. var expire = App.GetConfig<int>("JWTSettings:ExpiredTime");//获取过期时间(分钟)
  19. var currentHttpContext = context.GetCurrentHttpContext();
  20. //自动刷新Token
  21. if (JWTEncryption.AutoRefreshToken(context, currentHttpContext, expire, expire * 2))
  22. {
  23. //判断token是否有效
  24. if (CheckTokenFromRedis(currentHttpContext, expire))
  25. {
  26. await AuthorizeHandleAsync(context);
  27. }
  28. else
  29. {
  30. currentHttpContext.Response.StatusCode = 401;//返回401给授权筛选器用
  31. }
  32. }
  33. else
  34. {
  35. context.Fail();// 授权失败
  36. if (currentHttpContext == null)
  37. return;
  38. currentHttpContext.SignoutToSwagger();
  39. }
  40. }
  41. /// <summary>
  42. /// 检查token有效性
  43. /// </summary>
  44. /// <param name="context">DefaultHttpContext</param>
  45. /// <param name="expire">token有效期/分钟</param>
  46. /// <returns></returns>
  47. private bool CheckTokenFromRedis(DefaultHttpContext context, int expire)
  48. {
  49. var token = JWTEncryption.GetJwtBearerToken(context);//获取当前token
  50. var userId = App.User?.FindFirstValue(ClaimConst.USER_ID);//获取用户ID
  51. var simpleCacheService = App.GetService<ISimpleCacheService>();//获取redis实例
  52. var tokenInfos = simpleCacheService.HashGetOne<List<TokenInfo>>(CacheConst.CACHE_USER_TOKEN, userId);//获取token信息
  53. if (tokenInfos == null)//如果还是空
  54. {
  55. return false;
  56. }
  57. var tokenInfo = tokenInfos.Where(it => it.Token == token).FirstOrDefault();//获取redis中token值是当前token的对象
  58. if (tokenInfo != null)
  59. {
  60. // 自动刷新token返回新的Token
  61. var accessToken = context.Response.Headers["access-token"].ToString();
  62. if (!string.IsNullOrEmpty(accessToken))//如果有新的刷新token
  63. {
  64. "返回新的刷新token".LogDebug<JwtHandler>();
  65. tokenInfo.Token = accessToken;//新的token
  66. tokenInfo.TokenTimeout = DateTime.Now.AddMinutes(expire);//新的过期时间
  67. simpleCacheService.HashAdd(CacheConst.CACHE_USER_TOKEN, userId, tokenInfos);//更新token信息到redis
  68. }
  69. }
  70. else
  71. {
  72. return false;
  73. }
  74. return true;
  75. }
  76. /// <summary>
  77. /// 授权判断逻辑,授权通过返回 true,否则返回 false
  78. /// </summary>
  79. /// <param name="context"></param>
  80. /// <param name="httpContext"></param>
  81. /// <returns></returns>
  82. public override async Task<bool> PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
  83. {
  84. // 这里写您的授权判断逻辑,授权通过返回 true,否则返回 false
  85. // 此处已经自动验证 Jwt Token的有效性了,无需手动验证
  86. return await CheckAuthorizationAsync(httpContext);
  87. }
  88. /// <summary>
  89. /// 检查权限
  90. /// </summary>
  91. /// <param name="httpContext"></param>
  92. /// <returns></returns>
  93. private static async Task<bool> CheckAuthorizationAsync(DefaultHttpContext httpContext)
  94. {
  95. //超级管理员都能访问
  96. if (UserManager.SuperAdmin) return true;
  97. // 获取超级管理员特性
  98. var isSuperAdmin = httpContext.GetMetadata<SuperAdminAttribute>();
  99. if (isSuperAdmin != null)//如果是超级管理员才能访问的接口
  100. {
  101. //获取忽略超级管理员特性
  102. var ignoreSuperAdmin = httpContext.GetMetadata<IgnoreSuperAdminAttribute>();
  103. if (ignoreSuperAdmin == null && !UserManager.SuperAdmin)//如果只能超级管理员访问并且用户不是超级管理员
  104. return false;//直接没权限
  105. }
  106. //获取角色授权特性
  107. var isRolePermission = httpContext.GetMetadata<RolePermissionAttribute>();
  108. if (isRolePermission != null)
  109. {
  110. //获取忽略角色授权特性
  111. var ignoreRolePermission = httpContext.GetMetadata<IgnoreRolePermissionAttribute>();
  112. if (ignoreRolePermission == null)
  113. {
  114. // 路由名称
  115. var routeName = httpContext.Request.Path.Value;
  116. //获取用户信息
  117. var userInfo = await App.GetService<ISysUserService>().GetUserById(UserManager.UserId);
  118. if (!userInfo.PermissionCodeList.Contains(routeName))//如果当前路由信息不包含在角色授权路由列表中则认证失败
  119. return false;
  120. }
  121. }
  122. return true;
  123. }
  124. }