1. 程式人生 > 其它 >Shiro實現後臺認證和授權

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
  • 這兩個都看完了