最近使用springboot框架做了一个项目,其中使用了shiro进行登录认证和权限管理,这里给shiro模块做一个笔记。

导入shiro依赖

1 <dependency>
2     <groupId>org.apache.shiro</groupId>
3     <artifactId>shiro-spring-boot-web-starter</artifactId>
4     <version>1.4.1</version>
5 </dependency>
View Code

User实体类

1 public class User implements Serializable{
2     private static final long serialVersionUID = 1L;
3     private int userId;
4     private String userName;
5     private String password;
6     private boolean rememberMe;
7     private List<Role> roles;
8     //setter、getter...
9 }
View Code

Role实体类

1 public class Role {
2     private int roleId;
3     private String roleName;
4     private List<User> users;
5     private List<Resource> resources;
6     //setter、getter...
7 }
View Code

Resource实体类

1 public class Resource {
2     private int resourceId;
3     private String resourceUri;
4     private String resourceName;
5     private String permission;
6     private List<Role> roles;
7     //setter、getter
8 }
View Code

自定义Realm

 1 @Component
 2 public class MyRealm extends AuthorizingRealm {
 3     @Autowired
 4     private ResourceService resourceService;
 5     @Autowired
 6     private UserService userService;
 7 
 8 
 9 
10     /**
11      * 给用户授权
12      */
13     @Override
14     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
15         SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
16         //获取用户对象
17         User user = (User) principalCollection.getPrimaryPrincipal();
18         //获取用户的角色信息
19         List<Role> roles = user.getRoles();
20         if (roles != null && !roles.isEmpty()) {
21             //遍历当前用户的所有角色,将角色名添加到用户权限中
22             roles.forEach(role -> {
23                 simpleAuthorizationInfo.addRole(role.getRoleName());
24                 //获取每个角色能访问的资源
25                 List<Resource> resources =
26                         resourceService.getResourcesByRoleId(role.getRoleId());
27                 if (resources != null && !resources.isEmpty()) {
28                     //遍历当角色所能访问的资源,将资源的uri添加到用户权限中
29                     resources.forEach(resource ->
30                             simpleAuthorizationInfo.addStringPermission(resource.getResourceUri()));
31                 }
32             });
33         }
34         return simpleAuthorizationInfo;
35     }
36 
37     /**
38      * 用户认证
39      */
40     @Override
41     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
42         //获取令牌(即用户名)
43         String userName = (String) authenticationToken.getPrincipal();
44         //获取数据库中的用户信息,用于比对
45         User user = userService.getUserByUserName(userName);
46         if(user == null) {
47             throw new UnknownAccountException("用户名不存在");
48         }
49 
50         //设置盐
51         ByteSource salt = ByteSource.Util.bytes(userName+ MD5Util.getSALT());
52 
53         return new SimpleAuthenticationInfo(user,user.getPassword(),salt,getName());
54     }
55 
56 
57 }
View Code

shiro配置类

  1 @Configuration
  2 @Component
  3 public class ShiroConfig {
  4 
  5 
  6     /**
  7      * 配置Realm
  8      */
  9     @Bean
 10     public MyRealm realm() {
 11 
 12         MyRealm myRealm = new MyRealm();
 13         HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
 14         //设置加密方式
 15         hashedCredentialsMatcher.setHashAlgorithmName("MD5");
 16         //设置加密次数
 17         hashedCredentialsMatcher.setHashIterations(1024);
 18         myRealm.setCredentialsMatcher(hashedCredentialsMatcher);
 19 
 20         return myRealm;
 21     }
 22 
 23     /**
 24      * 注册默认的安全管理器
 25      */
 26     @Bean
 27     public DefaultSecurityManager securityManager() {
 28         DefaultSecurityManager manager = new DefaultWebSecurityManager();
 29         manager.setRealm(realm());
 30         return manager;
 31     }
 32 
 33     /**
 34      * 配置shiro过滤器工厂
 35      * -----------------
 36      * 拦截权限
 37      * anon:匿名访问,无需登录
 38      * authc:登录后才能访问
 39      * user:登录过能访问
 40      * logout:登出
 41      * roles:角色过滤器
 42      * ------------------
 43      * URL匹配风格
 44      * ?:匹配一个字符,如 /admin? 将匹配 /admin1,但不匹配 /admin 或 /admin/
 45      * *:匹配零个或多个字符串,如 /admin* 将匹配 /admin 或/admin123,但不匹配 /admin/1
 46      * **:匹配路径中的零个或多个路径,如 /admin/** 将匹配 /admin/a 或 /admin/a/b
 47      * -----------------------
 48      * 方法名不能乱写,如果我们定义为别的名称,又没有添加注册过滤器的配置,那么shiro会加载ShiroWebFilterConfiguration过滤器,
 49      * 该过滤器会寻找shiroFilterFactoryBean,找不到会抛出异常
 50      */
 51     @Bean
 52     public ShiroFilterFactoryBean shiroFilterFactoryBean() {
 53         ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
 54         shiroFilter.setSecurityManager(securityManager());
 55 
 56         shiroFilter.setLoginUrl("/account/loginVue");
 57         shiroFilter.setSuccessUrl("/account/dashboard");
 58 
 59         Map<String,String> map = new LinkedHashMap<>();
 60         map.put("/", "authc");
 61         map.put("/static/**", "anon");
 62         map.put("/js/**", "anon");
 63         map.put("/css/**", "anon");
 64         map.put("/plugin/**", "anon");
 65         map.put("/account/login", "anon");
 66         map.put("/account/loginVue", "anon");
 67         map.put("/api/login", "anon");
 68         map.put("/account/register", "anon");
 69         map.put("/account/registerVue", "anon");
 70         map.put("/api/user", "anon");
 71 
 72         map.put("/common/**", "user");
 73         map.put("/test/**", "user");
 74         map.put("/**", "authc");
 75 
 76         shiroFilter.setFilterChainDefinitionMap(map);
 77 
 78         return shiroFilter;
 79     }
 80 
 81     /**
 82      * 注册ShiroDialect,让thymeleaf支持shiro标签
 83      */
 84     @Bean
 85     public ShiroDialect shiroDialect() {
 86         return new ShiroDialect();
 87     }
 88 
 89     /**
 90      * 自动代理类,支持Shiro的注解
 91      */
 92     @Bean
 93     @DependsOn({"lifecycleBeanPostProcessor"})
 94     public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
 95         DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator =
 96                 new DefaultAdvisorAutoProxyCreator();
 97         advisorAutoProxyCreator.setProxyTargetClass(true);
 98         return advisorAutoProxyCreator;
 99     }
100 
101     /**
102      * 开启Shiro的注解
103      */
104     @Bean
105     public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
106         AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor =
107                 new AuthorizationAttributeSourceAdvisor();
108         authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
109         return authorizationAttributeSourceAdvisor;
110     }
111 }
View Code

UserServiceImpl类

 1 @Service
 2 public class UserServiceImpl implements UserService {
 3 
 4     @Override
 5     public Result<User> login(User user) {
 6         //获取当前的用户
 7         Subject subject = SecurityUtils.getSubject();
 8 
 9         //将传来的user信息封装到UsernamePasswordToken
10         UsernamePasswordToken usernamePasswordToken =
11                 new UsernamePasswordToken(user.getUserName(),
12                         user.getPassword());
13         usernamePasswordToken.setRememberMe(user.getRememberMe());
14 
15         try {
16             //登录验证
17             subject.login(usernamePasswordToken);
18             subject.checkRoles();
19         } catch (AuthenticationException e) {
20             e.printStackTrace();
21             return new Result<>(Result.ResultStatus.FAILED.status,
22                     "用户名或密码错误");
23         }
24 
25         //将用户信息加入到session里
26         Session session = subject.getSession();
27         session.setAttribute("user",subject.getPrincipal());
28         return new Result<>(Result.ResultStatus.SUCCESS.status,
29                 "登录成功", user);
30     }
31 
32     @Override
33     public void logout() {
34         Subject subject = SecurityUtils.getSubject();
35         subject.logout();
36         Session session = subject.getSession();
37         session.removeAttribute("user");
38     }
39 }
View Code

 

posted on 2020-08-26 16:51  云中火  阅读(186)  评论(0)    收藏  举报