shiro登录过程

工作流程:

浏览器将用户名、密码、是否记住登录等信息发送给登录controller ,

new UsernamePasswordToken()获取token,将用户名、加密后的密码、rememberMe,set到token中。SecurityUtils.getSubject();获取subject对象,执行subect.login(token)进行登录操作并捕获可能出现的账号密码错误等异常。

 

1.前端登录页面将用户名、密码、是否记住登录,传入到Controller
Controller登录方法:
 1 //1.获取shiro中的subject对象
 2 Subject subject = SecurityUtils.getSubject();
 3 //2.对用户从页面输入的密码进行加密处理
 4 password = new Md5Hash(password,username,1024).toString();
 5 System.out.println("加密后的密码: " + password);
 6 //3.创建shiro中的用户名和密码对象,将用户输入的用户名密码交给shiro管理
 7 UsernamePasswordToken token = new UsernamePasswordToken(username, password);
 8 //4.关于记住我的设置
 9 System.out.println("是否记住我: " + rememberMe);
10 if(rememberMe){
11     token.setRememberMe(true);
12 }
13 //5.调用shiro的登录方法,调用后,shiro会自动执行Realm实现类===========
14 try {
15     subject.login(token);
16     System.out.println("开始登陆");
17 } catch (UnknownAccountException e) {
18     return new Result(1, "账号不存在");
19 }catch (IncorrectCredentialsException e){
20     return new Result(1,"密码错误");
21 }catch (AuthenticationException e){
22     System.out.println("其他异常");
23     return new Result(1,"其他异常");
24 }
25 return new Result(0, "登陆成功!");
26 
27 /**
28  * 注销方法
29  * @return
30  */
31 public Result logout(){
32     //1.获取subject对象
33     Subject subject =  SecurityUtils.getSubject();
34     //2.返回注销方法
35     subject.logout();
36     //3.返回
37     return Result.ok("注销成功");
38 }

获取完数据后,shiro会自动执行Realm的实现类,实现类需要手动实现,如下:

 1 /**
 2  * projectName: myproject
 3  * @author: xxx
 4  * time: 2021/9/6 21:17
 5  * description:  自定义realm对象
 6  *
 7  *  1.从数据库根据用户名,取出数据库中的用户名,密码交给shiro框架
 8  *  2.根据用户名,到数据库取出用户对应的角色和权限对象交给shiro框架管理
 9  */
10 
11 public class MyUserRealm extends AuthorizingRealm {
12 
13     @Autowired
14     private UserService userService;
15     @Autowired
16     private MenuService menuService;
17     @Autowired
18     private RoleService roleService;
19     
20     /**
21      *     用户输入的用户名和密码输入正确,校验完成后进行赋值操作
22      *     根据用户名到数据库查询这个用户对应的角色和权限,交给shiro管理
23      *     调用时机:在需要访问资源的时候,需要角色和权限的视乎才会调用此方法
24      * @param principalCollection
25      * @return
26      */
27     @Override
28     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
29 
30         System.out.println("已登陆成功,授予登录用户权限,也就是赋予用户对应的角色和能够访问的菜单");
31 
32         //1.获取当前登录的用户对象
33         SysUsers sysUSers = (SysUsers) principalCollection.getPrimaryPrincipal();
34 
35         //2.获取当前登录用户的 用户id
36         int uid = sysUSers.getId();
37 
38         //3.根据用户id,查询数据库中这个用户对应的角色集合和权限集合
39         Set<String> roleList = roleService.findRoleListByUid(uid);
40         Set<String> menuList = menuService.findMenuListbyUid(uid);
41 
42         //4.创建shiro中的用户权限对象
43         SimpleAuthorizationInfo auth = new SimpleAuthorizationInfo();
44 
45         //5.将查询到的角色集合放入shiro的权限对象
46         auth.setRoles(roleList);
47 
48         //6.将查询到的权限集合放入shiro的权限对象
49         auth.setStringPermissions(menuList);
50 
51         //7.返回shiro权限对象
52         return auth;
53     }
54 
55     /**
56      *     根据用户在页面输入的用户名,查询数据库中的用户名和密码,交给shiro框架
57      *     让shiro框架进行对比用户名,密码是否正确
58      *    调用时机:在controller调用subject.login(token);方法就会执行这个方法,进行用户名 密码校验
59      * @param auth
60      * @return
61      * @throws AuthenticationException
62      */
63     @Override
64     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
65         System.out.println("开始校验用户名和密码................");
66 
67         //1.获取用户在浏览器输入的用户名
68         String userName = (String) auth.getPrincipal();
69         //2.根据用户输入的用户名,查询数据库的用户对象
70         String password = new String((char[]) auth.getCredentials());
71         //3.判断用户是否为空,为空则抛出异常
72         SysUsers sysUSer = userService.findUserbyName(userName);
73         if (sysUSer == null) {
74             throw new UnknownAccountException("账号不存在,请先注册,再登录!");
75         }
76         //4.对比数据库的密码和用户输入的密码是否一致
77         if(!password.equals(sysUSer.getPassword())){
78             throw new IncorrectCredentialsException("密码错误");
79         }
80         //5.判断用户状态,1正常,其他为锁定状态
81         if(sysUSer.getStatus() != 1){
82             throw new LockedAccountException("账号被锁定不允许登录");
83         }
84         //6.封装shiro中需要的权限对象,包括用户名 密码 以及当前用户对象交给shiro返回
85         SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName, password, this.getName());
86         return info;
87     }
88 }

其他Controller方法需要做权限验证时,可以在上面加注解@RequiresPermissions("sys:product:add")

括号里是权限字符串,用冒号连接

shiro注解用在Service和Controller层,但是如果Service层有事务注解,那么shiro注解要放在Controller层。因为两个代理对象在类型转换时会出现异常。



posted @ 2021-10-15 11:41  黄大虾  阅读(2158)  评论(0编辑  收藏  举报