Spring Boot集成Shiro

0.前言

  Shiro簡單來說就是一個做權限鑑定與管理的一個工具。在搭建spring boot 集成Shrio的demo的時候,我們需要做一個前期的準備(demo中有sql文件),demo在這裏
數據庫表:
在這裏插入圖片描述
Maven

        <!--shiro和spring整合-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!--shiro核心包-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.3.2</version>
        </dependency>

1.登錄的controller

    /**
     * 1.傳統登錄
     * 前端發送登錄請求 => 接口部分獲取用戶名密碼 => 程序員在接口部分手動控制
     * 2.shiro登錄
     * 前端發送登錄請求 => 接口部分獲取用戶名密碼 => 通過subject.login =>  realm域的認證方法
     */
    @RequestMapping(value = "/login")
    public String login(String username, String password) {
        //構造登錄令牌
        try {

            /**
             * 密碼加密:
             *     shiro提供的md5加密
             *     Md5Hash:
             *      參數一:加密的內容
             *              111111   --- abcd
             *      參數二:鹽(加密的混淆字符串)(用戶登錄的用戶名)
             *              111111+混淆字符串
             *      參數三:加密次數
             *
             */
            password = new Md5Hash(password, username, 3).toString();
            System.out.println(username + "==>" + password);
            UsernamePasswordToken upToken = new UsernamePasswordToken(username, password);
            //1.獲取subject
            Subject subject = SecurityUtils.getSubject();

            //獲取session
            String sid = (String) subject.getSession().getId();

            //2.調用subject進行登錄
            subject.login(upToken);
            return "登錄成功:" + sid;
        } catch (Exception e) {
            return "用戶名或密碼錯誤";
        }
    }

2. 自定義的Realm域

用來做權限的認證和授權,跟數據庫進行交互,獲取相應的權限或者角色信息,controller中使用subject.login(upToken);方法的時候就會執行這裏的一些方法

/**
 * 自定義的realm
 */
public class CustomRealm extends AuthorizingRealm {

    @Override
    public void setName(String name) {
        super.setName("customRealm");
    }

    @Autowired
    private UserService userService;

    /**
     * 授權方法
     *      操作的時候,判斷用戶是否具有響應的權限
     *          先認證 -- 安全數據
     *          再授權 -- 根據安全數據獲取用戶具有的所有操作權限
     *
     *
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //1.獲取已認證的用戶數據
        User user = (User) principalCollection.getPrimaryPrincipal();//得到唯一的安全數據
        //2.根據用戶數據獲取用戶的權限信息(所有角色,所有權限)
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Set<String> roles = new HashSet<>();//所有角色
        Set<String> perms = new HashSet<>();//所有權限
        for (Role role : user.getRoles()) {
            roles.add(role.getName());
            for (Permission perm : role.getPermissions()) {
                perms.add(perm.getCode());
            }
        }
        info.setStringPermissions(perms);
        info.setRoles(roles);
        return info;
    }


    /**
     * 認證方法
     *  參數:傳遞的用戶名密碼
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1.獲取登錄的用戶名密碼(token)
        UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
        String username = upToken.getUsername();
        String password = new String( upToken.getPassword());
        //2.根據用戶名查詢數據庫
        User user = userService.findByName(username);
        //3.判斷用戶是否存在或者密碼是否一致
        if(user != null && user.getPassword().equals(password)) {
            System.out.println("用戶名和密碼正確,登陸成功");
            //4.如果一致返回安全數據
            //構造方法:安全數據,密碼,realm域名
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
            return info;
        }
        //5.不一致,返回null(拋出異常)
        return null;
    }
}

3.配置類

@Configuration
public class ShiroConfiguration {

    //1.創建realm
    @Bean
    public CustomRealm getRealm() {
        return new CustomRealm();
    }

    //2.創建安全管理器
    @Bean
    public SecurityManager getSecurityManager(CustomRealm realm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);

        //將自定義的會話管理器註冊到安全管理器中
        securityManager.setSessionManager(sessionManager());
        //將自定義的redis緩存管理器註冊到安全管理器中
        securityManager.setCacheManager(cacheManager());

        return securityManager;
    }

    //3.配置shiro的過濾器工廠

    /**
     * 再web程序中,shiro進行權限控制全部是通過一組過濾器集合進行控制
     *
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        //1.創建過濾器工廠
        ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
        //2.設置安全管理器
        filterFactory.setSecurityManager(securityManager);
        //3.通用配置(跳轉登錄頁面,爲授權跳轉的頁面)
        filterFactory.setLoginUrl("/autherror?code=1");//跳轉url地址
        filterFactory.setUnauthorizedUrl("/autherror?code=2");//未授權的url
        //4.設置過濾器集合

        /**
         * 設置所有的過濾器:有順序map
         *     key = 攔截的url地址
         *     value = 過濾器類型
         *
         */
        Map<String,String> filterMap = new LinkedHashMap<>();
        filterMap.put("/user/home","anon");//當前請求地址可以匿名訪問

        //具有某種權限才能訪問
        //使用過濾器的形式配置請求地址的依賴權限
        //filterMap.put("/user/home","perms[user-home]"); //不具備指定的權限,跳轉到setUnauthorizedUrl地址

        //使用過濾器的形式配置請求地址的依賴角色
        //filterMap.put("/user/home","roles[系統管理員]");

        filterMap.put("/user/**","authc");//當前請求地址必須認證之後可以訪問

        filterFactory.setFilterChainDefinitionMap(filterMap);

        return filterFactory;
    }

    //開啓對shior註解的支持
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
}

4.關於demo的說明

demo中使用了redis,用來存儲sessionId,demo是學習這套視頻,大家也可以參考一些

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章