Shiro實現後臺認證和授權
阿新 • • 發佈:2021-06-26
技術概述
使用Shiro是為了實現後臺的認證與授權。Shiro簡單易用,不與任何框架捆綁。沒有難點。
技術詳述
-
1.在pom.xml中新增依賴
<!-- shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-starter</artifactId> <version>1.4.0</version> </dependency>
-
2.建立認證和授權對應的表
user、role、permission
-
3.編寫對應的dao、service
@Mapper @Repository public interface RoleDAO { /** * 根據管理員id查詢對應的角色 * * @param adminId * @return */ List<RoleDO> listRoleDOByAdminId(Long adminId); }
@Mapper @Repository public interface PermissionDAO { /** * 根據角色的id返回所具有的許可權 * * @param roleId * @return */ List<PermissionDO> listPermissionDOByRoleId(long roleId); }
-
4.建立自定義的realm
public class AdminShiroRealm extends AuthorizingRealm { @Autowired AdminService adminService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); String account = (String) principals.getPrimaryPrincipal(); AdminDO adminDO = new AdminDO(); adminDO.setAccount(account); AdminBO adminBO = adminService.getAdminBoByDO(adminDO); List<RoleDO> roleDOList = adminService.getRoleDoByAdminBO(adminBO); for (RoleDO roleDO : roleDOList) { authorizationInfo.addRole(roleDO.getRoleName()); List<PermissionDO> permissionDOList = adminService.getPermissionDOByRoleDO(roleDO); for (PermissionDO permissionDO : permissionDOList) { authorizationInfo.addStringPermission(permissionDO.getPermission()); } } return authorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String account = (String) token.getPrincipal(); AdminDO adminDO = new AdminDO(); adminDO.setAccount(account); AdminBO adminBO = adminService.getAdminBoByDO(adminDO); if (adminBO == null) { return null; } SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(adminBO.getAccount(), adminBO.getPassword(), ByteSource.Util.bytes(adminBO.getSalt()), getName()); return authenticationInfo; } }
-
5.配置Shiro
@Configuration public class ShiroConfig { @Bean public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager((org.apache.shiro.mgt.SecurityManager) securityManager); Map<String, String> filterChainDefinitionMap = new HashMap<String, String>(); shiroFilterFactoryBean.setLoginUrl("/admin/login"); filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName(PasswordHelper.ALGORITHM_NAME); // 雜湊演算法 hashedCredentialsMatcher.setHashIterations(PasswordHelper.HASH_ITERATIONS); // 雜湊次數 return hashedCredentialsMatcher; } @Bean public AdminShiroRealm shiroRealm() { AdminShiroRealm shiroRealm = new AdminShiroRealm(); shiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); // 原來在這裡 return shiroRealm; } @Bean public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(shiroRealm()); return securityManager; } //加入註解的使用 @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } }
-
6.編寫controller
@RestController @RequestMapping("/admin") public class AdminLoginController { @Autowired AdminService adminService; @PostMapping("/login") public String login(HttpServletRequest request, HttpSession session) { String account = request.getParameter("account"); String password = request.getParameter("password"); UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(account, password); Subject subject = SecurityUtils.getSubject(); try { subject.login(usernamePasswordToken); } catch (IncorrectCredentialsException ice) { return JSON.toJSONString(Result.failureResult(ResultCode.PASSWORD_ERROR)); } catch (UnknownAccountException uae) { return JSON.toJSONString(Result.failureResult(ResultCode.ACCOUNT_ERROR)); } AdminDO adminDO = new AdminDO(); adminDO.setAccount(account); AdminBO adminBo = adminService.getAdminBoByDO(adminDO); session.setAttribute("admin", adminBo); adminDO.setId(adminBo.getId()); AdminVO adminVO=new AdminVO(); adminVO.setAccount(adminBo.getAccount()); adminVO.setId(adminBo.getId()); adminVO.setToken(TokenUtil.getToken(adminBo)); return JSON.toJSONString(Result.successResult(adminVO)); } }
-
流程圖
技術使用中遇到的問題和解決過程
-
問題:登入成功後忘記返回token了
解決:返回token
adminVO.setToken(TokenUtil.getToken(adminBo)); return JSON.toJSONString(Result.successResult(adminVO));
進行總結
- Shiro 是一個強大而靈活的開源安全框架,能夠非常清晰的處理認證、授權、管理會話以及密碼加密。在實現認證和授權的時候使用Shiro可以快速實現,同時shiro不與平臺繫結,十分的便捷
列出參考文獻、參考部落格
- Shiro跟著b站視訊學的來著
- 尚矽谷、狂神說Java
- 這兩個都看完了