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));
        }
    
    }
    
    
  • 流程图

    img

技术使用中遇到的问题和解决过程

  • 问题:登录成功后忘记返回token了

    解决:返回token

    adminVO.setToken(TokenUtil.getToken(adminBo));
    return JSON.toJSONString(Result.successResult(adminVO));
    

进行总结

  • Shiro 是一个强大而灵活的开源安全框架,能够非常清晰的处理认证、授权、管理会话以及密码加密。在实现认证和授权的时候使用Shiro可以快速实现,同时shiro不与平台绑定,十分的便捷

列出参考文献、参考博客

  • Shiro跟着b站视频学的来着
  • 尚硅谷、狂神说Java
  • 这两个都看完了
posted @ 2021-06-26 16:42  221801326_王炜嘉  阅读(190)  评论(0编辑  收藏  举报