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

143 lines
5.1 KiB

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