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层。因为两个代理对象在类型转换时会出现异常。