UserRealm.java 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package com.usky.config.shiro;
  2. import com.usky.config.shiro.jwt.JwtToken;
  3. import com.usky.constant.Constant;
  4. import com.usky.entity.sys.vo.SysUserVO;
  5. import com.usky.service.sys.menuService.MenuService;
  6. import com.usky.service.sys.user.UserService;
  7. import com.usky.utils.AuthorizationUtils;
  8. import com.usky.utils.RedisUtil;
  9. import com.usky.utils.jwt.JwtUtil;
  10. import com.usky.utils.jwt.common.StringUtil;
  11. import lombok.extern.slf4j.Slf4j;
  12. import org.apache.shiro.authc.AuthenticationException;
  13. import org.apache.shiro.authc.AuthenticationInfo;
  14. import org.apache.shiro.authc.AuthenticationToken;
  15. import org.apache.shiro.authc.SimpleAuthenticationInfo;
  16. import org.apache.shiro.authz.AuthorizationInfo;
  17. import org.apache.shiro.authz.SimpleAuthorizationInfo;
  18. import org.apache.shiro.realm.AuthorizingRealm;
  19. import org.apache.shiro.subject.PrincipalCollection;
  20. import org.apache.shiro.subject.SimplePrincipalCollection;
  21. import org.springframework.context.annotation.Lazy;
  22. import org.springframework.stereotype.Service;
  23. import javax.annotation.Resource;
  24. import java.util.Set;
  25. @Service
  26. @Slf4j
  27. public class UserRealm extends AuthorizingRealm {
  28. @Resource
  29. @Lazy
  30. private UserService userService;
  31. @Resource
  32. @Lazy
  33. private MenuService menuService;
  34. @Resource
  35. @Lazy
  36. private RedisUtil redisUtil;
  37. @Override
  38. public boolean supports(AuthenticationToken authenticationToken) {
  39. return authenticationToken instanceof JwtToken;
  40. }
  41. /**
  42. * 只有当需要检测用户权限的时候才会调用此方法,例如checkRole,checkPermission之类的
  43. */
  44. @Override
  45. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
  46. SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
  47. String loginName = JwtUtil.getClaim(principalCollection.toString(), Constant.ACCOUNT);
  48. if (StringUtil.isBlank(loginName)) {
  49. throw new AuthenticationException("Token中帐号为空");
  50. }
  51. SysUserVO sysUser = userService.queryuserByLoginName(loginName);
  52. if (sysUser != null) {
  53. // 角色列表
  54. Set<String> roles;
  55. // 功能列表
  56. Set<String> menus;
  57. log.info("===============Shiro权限认证开始============ [ roles、permissions]==========");
  58. if (sysUser.isAdmin()) {
  59. simpleAuthorizationInfo.addRole("admin");
  60. simpleAuthorizationInfo.addStringPermission("*:*:*");
  61. } else {
  62. roles = userService.queryRoleKeys(sysUser.getUserId());
  63. menus = menuService.qyeryPermsByUserId(sysUser.getUserId());
  64. // 角色加入AuthorizationInfo认证对象
  65. simpleAuthorizationInfo.setRoles(roles);
  66. // 权限加入AuthorizationInfo认证对象
  67. simpleAuthorizationInfo.setStringPermissions(menus);
  68. }
  69. log.info("===============Shiro权限认证成功==============");
  70. }
  71. return simpleAuthorizationInfo;
  72. }
  73. /**
  74. * 默认使用此方法进行用户名正确与否验证,错误抛出异常即可。
  75. */
  76. @Override
  77. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
  78. String token = (String) authenticationToken.getCredentials();
  79. // 解密获得account,用于和数据库进行对比
  80. String loginName = JwtUtil.getClaim(token, "loginName");
  81. // 帐号为空
  82. if (StringUtil.isBlank(loginName)) {
  83. throw new AuthenticationException("Token中帐号为空");
  84. }
  85. // 查询用户是否存在
  86. SysUserVO sysUser = userService.queryuserByLoginName(loginName);
  87. if (sysUser == null) {
  88. throw new AuthenticationException("该帐号不存在");
  89. }
  90. // 开始认证,要AccessToken认证通过,且Redis中存在RefreshToken,且两个Token时间戳一致
  91. if (JwtUtil.verify(token) && redisUtil.hasKey(Constant.PREFIX_SHIRO_REFRESH_TOKEN + loginName)) {
  92. // 获取RefreshToken的时间戳
  93. String currentTimeMillisRedis = redisUtil.get(Constant.PREFIX_SHIRO_REFRESH_TOKEN + loginName).toString();
  94. // 获取AccessToken时间戳,与RefreshToken的时间戳对比
  95. if (JwtUtil.getClaim(token, Constant.CURRENT_TIME_MILLIS).equals(currentTimeMillisRedis)) {
  96. return new SimpleAuthenticationInfo(token, token, "userRealm");
  97. }
  98. }
  99. throw new AuthenticationException("Token已过期");
  100. }
  101. /**
  102. * 清除当前用户的权限认证缓存
  103. *
  104. * @param principals 权限信息
  105. */
  106. @Override
  107. public void clearCache(PrincipalCollection principals) {
  108. super.clearCache(principals);
  109. }
  110. /**
  111. * 清理所有用户授权信息缓存
  112. */
  113. public void clearAllCachedAuthorizationInfo() {
  114. AuthorizationUtils.clearAllCachedAuthorizationInfo();
  115. }
  116. }