Shiro实现后台认证和授权
技术概述
使用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
- 这两个都看完了