1. 程式人生 > >Shiro與SpringBoot整合

Shiro與SpringBoot整合

SpringBoot框架現階段使用的比較頻繁,但是Spring家族中的安全管理框架(Spring Security)的功能雖然強大,但是他是給予Spring的,不能單獨使用,而Shiro則相對簡單,容易上手,所以這裡簡單記錄一下SpringBoot框架整合Shiro。
這裡寫圖片描述
首先要有一個 SpringBoot的架構,我的springboot的目錄為
這裡寫圖片描述
整合主要在這個框架中加入兩個實現類,功能分別為
- 登入許可權驗證以及角色驗證
- 配置要攔截的介面,以及密碼的加密等等
需要匯入的jar包為:

<dependency>
            <groupId
>
org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId
>
<version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.2.2</version> </dependency> <dependency
>
<groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.5</version> </dependency>

下面為第一個實現類

public class ShiroRealm extends AuthorizingRealm {
    /**
     * 1.doGetAuthenticationInfo,獲取認證訊息,如果資料庫中沒有數,返回null,如果得到了正確的使用者名稱和密碼,
     * 返回指定型別的物件
     *
     * 2.AuthenticationInfo 可以使用SimpleAuthenticationInfo實現類,封裝正確的使用者名稱和密碼。
     *
     * 3.token引數 就是我們需要認證的token
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */

    //認證登入
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 1.將token裝換成UsernamePasswordToken
        UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
        logger.info("驗證當前Subject時獲取到token為:" + upToken.toString());
        // 2.獲取使用者名稱即可
        String username = upToken.getUsername();
        // 3.查詢資料庫,是否查詢到使用者名稱和密碼的使用者
        UserInfoEntity userInfo = userInfoService.selectByPhone(username);

        if(userInfo != null) {
            // 4.如果查詢到了,封裝查詢結果,返回給我們的呼叫
            Object principal =  userInfo.getPhoneNumber();
            Object credentials = userInfo.getPassword();
            ByteSource salt = ByteSource.Util.bytes(username);
            String realmName = this.getName();
            info = new SimpleAuthenticationInfo(principal, credentials, salt,realmName);
        }else {
            // 5.如果沒有查詢到,丟擲一個異常
            throw new AuthenticationException();

        }

        return info;
    }

    //授權
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        logger.info("##################執行Shiro許可權認證##################");
        String username = (String) principalCollection.getPrimaryPrincipal();
        EnterpriseInfoEntity user = enterpriseInfoEntityMapper.selectByPhone(username);

        if (user != null) {
            //許可權資訊物件info,用來存放查出的使用者的所有的角色(role)及許可權(permission)
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            //使用者的角色集合
            Set<String> list = new HashSet<>();
            list.add(user.getAuditStatus());
            info.addRoles(list);
            //使用者的許可權集合
            info.addStringPermissions(list);

            return info;
        }
        // 返回null的話,就會導致任何使用者訪問被攔截的請求時,都會自動跳轉到unauthorizedUrl指定的地址
        return null;
    }
}

程式碼裡的註釋都很全,這裡就不做過多的介紹了,繼續來看第二個類

package com.aim.chenapp.config;


import com.aim.chenapp.beans.ShiroRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        System.out.println("ShiroConfiguration.shirFilter()");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //攔截器.
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 配置不會被攔截的連結 順序判斷
        //配置退出 過濾器,其中的具體的退出程式碼Shiro已經替我們實現了
        //靜態資源
        //filterChainDefinitionMap.put("/myTest/**", "anon");




        //需要企業使用者許可權的介面
        filterChainDefinitionMap.put("/newsInfo/selectNewsBySecond", "authc,roles[1]");//政策解讀
        filterChainDefinitionMap.put("/newsInfo/selectByCustomized", "authc,roles[1]");//法律定製





//        filterChainDefinitionMap.put("/user/login", "anon");
//        filterChainDefinitionMap.put("/user/unPower", "anon");
//        filterChainDefinitionMap.put("/user/doRegister", "anon");
        filterChainDefinitionMap.put("/**", "anon");


        //配置這個介面只能由admin這個角色訪問
        filterChainDefinitionMap.put("/user/selectAll", "authc,roles[admin]");

//        filterChainDefinitionMap.put("/user/doLogout", "logout");
        //<!-- 過濾鏈定義,從上向下順序執行,一般將/**放在最為下邊 -->:這是一個坑呢,一不小心程式碼就不好使了;
        //<!-- authc:所有url都必須認證通過才可以訪問; anon:所有url都都可以匿名訪問-->
        //filterChainDefinitionMap.put("/**", "authc");
        // 如果不設定預設會自動尋找Web工程根目錄下的"/login.jsp"頁面
        shiroFilterFactoryBean.setLoginUrl("/user/unPower");
        //未授權介面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    @Bean(name = "myShiroRealm")
    public ShiroRealm myShiroRealm(HashedCredentialsMatcher matcher){
        ShiroRealm myShiroRealm = new ShiroRealm();
//        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher("MD5");
//        matcher.setHashIterations(1024);
        myShiroRealm.setCredentialsMatcher(matcher);
        return myShiroRealm;
    }
    @Bean
    public SecurityManager securityManager(@Qualifier("hashedCredentialsMatcher") HashedCredentialsMatcher matcher){
        DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm(matcher));
        return securityManager;
    }

    /**
     * 密碼匹配憑證管理器
     *
     * @return
     */
    @Bean(name = "hashedCredentialsMatcher")
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();

        hashedCredentialsMatcher.setHashAlgorithmName("MD5");// 雜湊演算法:這裡使用MD5演算法;
        hashedCredentialsMatcher.setHashIterations(1024);// 雜湊的次數,比如雜湊兩次,相當於
        // md5(md5(""));

        return hashedCredentialsMatcher;
    }
}

這個就是SpringBoot框架整合Shiro的全部過程,如果有什麼問題歡迎留言探討。

青春短暫,我_在路上