工作流程:
瀏覽器將用戶名、密碼、是否記住登錄等信息發送給登錄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層。因為兩個代理對象在類型轉換時會出現異常。