MyRealm.java 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package com.fd.shiro;
  2. import com.fd.entity.UserEntity;
  3. import com.fd.repository.UserRepository;
  4. import lombok.extern.log4j.Log4j2;
  5. import org.apache.shiro.authc.AuthenticationException;
  6. import org.apache.shiro.authc.AuthenticationInfo;
  7. import org.apache.shiro.authc.AuthenticationToken;
  8. import org.apache.shiro.authc.SimpleAuthenticationInfo;
  9. import org.apache.shiro.authz.AuthorizationInfo;
  10. import org.apache.shiro.authz.SimpleAuthorizationInfo;
  11. import org.apache.shiro.realm.AuthorizingRealm;
  12. import org.apache.shiro.subject.PrincipalCollection;
  13. import org.springframework.beans.factory.annotation.Autowired;
  14. import org.springframework.data.redis.core.RedisTemplate;
  15. import org.springframework.stereotype.Service;
  16. import java.util.Arrays;
  17. import java.util.HashSet;
  18. import java.util.Set;
  19. /**
  20. * 配置不校验的话,是不会走这个方法的
  21. */
  22. @Log4j2
  23. @Service
  24. public class MyRealm extends AuthorizingRealm {
  25. @Autowired
  26. private UserRepository userRepository;
  27. @Autowired
  28. private RedisTemplate redisTemplate;
  29. /**
  30. * 大坑!,必须重写此方法,不然Shiro会报错
  31. */
  32. @Override
  33. public boolean supports(AuthenticationToken token) {
  34. return token instanceof JWTToken;
  35. }
  36. /**
  37. * 只有当需要检测用户权限的时候才会调用此方法,例如checkRole,checkPermission之类的
  38. *
  39. * principals: 是token
  40. */
  41. @Override
  42. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  43. String username = JWTUtil.getUsername(principals.toString());
  44. UserEntity user = userRepository.findByUsername(username);
  45. SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
  46. simpleAuthorizationInfo.addRole(user.getRole());
  47. // db 添加权限时,用“,”隔开
  48. Set<String> permission = new HashSet<>(Arrays.asList(user.getPermission().split(",")));
  49. simpleAuthorizationInfo.addStringPermissions(permission);
  50. return simpleAuthorizationInfo;
  51. }
  52. /**
  53. * 默认使用此方法进行用户名正确与否验证,错误抛出异常即可。
  54. */
  55. @Override
  56. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
  57. // log.warn("run doGetAuthenticationInfo");
  58. String token = (String) auth.getCredentials();
  59. // log.warn("token: {}", token);
  60. // 解密获得username,用于和数据库进行对比
  61. String username = JWTUtil.getUsername(token);
  62. if (username == null) {
  63. log.info("error token username");
  64. throw new AuthenticationException("token invalid");
  65. }
  66. UserEntity user = userRepository.findByUsername(username);
  67. if (user == null) {
  68. log.info("error token user");
  69. throw new AuthenticationException("User didn't existed!");
  70. }
  71. // 校验请求token是否跟redis token一致
  72. String redisToken = (String) redisTemplate.opsForValue().get(user.getUsername());
  73. if (!token.equals(redisToken)) {
  74. log.info("error token redis");
  75. // throw new AuthenticationException("token invalid");
  76. throw new AuthenticationException("token invalid");
  77. }
  78. if (! JWTUtil.verify(token, username, user.getPassword())) {
  79. log.info("error token username or password");
  80. throw new AuthenticationException("token invalid");
  81. }
  82. // log.warn("end doGetAuthenticationInfo");
  83. return new SimpleAuthenticationInfo(token, token, "my_realm");
  84. }
  85. }