Spring boot整合shiro框架


 

ShiroConfiguration

package com.energy.common.config;

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

import javax.servlet.Filter;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import com.energy.common.util.MyFormAuthenticationFilter;
import com.energy.common.util.MyShiroRealm;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;

/**
 * shiro配置類
 * 
 * @author lit
 *
 */
@Configuration
public class ShiroConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class);

    /**
     * LifecycleBeanPostProcessor,這是個DestructionAwareBeanPostProcessor的子類,
     * 負責org.apache.shiro.util.Initializable類型bean的生命周期的,初始化和銷毀。
     * 主要是AuthorizingRealm類的子類,以及EhCacheManager類。
     * 
     * @return
     */
    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        logger.info("ShiroConfiguration.getLifecycleBeanPostProcessor()");
        return new LifecycleBeanPostProcessor();
    }

    /**
     * HashedCredentialsMatcher,這個類是為了對密碼進行編碼的,防止密碼在數據庫里明碼保存,
     * 當然在登陸認證的生活,這個類也負責對form里輸入的密碼進行編碼。
     * 
     * @return
     */
    // @Bean(name = "hashedCredentialsMatcher")
    // public HashedCredentialsMatcher hashedCredentialsMatcher() {
    // HashedCredentialsMatcher credentialsMatcher = new
    // HashedCredentialsMatcher();
    // credentialsMatcher.setHashAlgorithmName("MD5");
    // credentialsMatcher.setHashIterations(2);
    // credentialsMatcher.setStoredCredentialsHexEncoded(true);
    // return credentialsMatcher;
    // }
    /**
     * ShiroRealm,這是個自定義的認證類,繼承自AuthorizingRealm, 負責用戶的認證和權限的處理
     * 
     * @return
     */
    @Bean(name = "myShiroRealm")
    @DependsOn("lifecycleBeanPostProcessor")
    public MyShiroRealm myShiroRealm() {
        logger.info("ShiroConfiguration.myShiroRealm()");
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        return myShiroRealm;
    }

    /**
     * EhCacheManager,緩存管理,用戶登陸成功后,把用戶信息和權限信息緩存起來,
     * 然后每次用戶請求時,放入用戶的session中,如果不設置這個bean,每個請求都會查詢一次數據庫。
     * 
     * @return
     */
    @Bean(name = "ehCacheManager")
    @DependsOn("lifecycleBeanPostProcessor")
    public EhCacheManager ehCacheManager() {
        logger.info("ShiroConfiguration.ehCacheManager()");
        EhCacheManager cacheManager = new EhCacheManager();
        cacheManager.setCacheManagerConfigFile("classpath:config/ehcache-shiro.xml");
        return cacheManager;
    }

    @Bean(name = "rememberMeCookie")
    public SimpleCookie rememberMeCookie() {
        logger.info("ShiroConfiguration.rememberMeCookie()");
        // 這個參數是cookie的名稱,對應前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        // <!-- 記住我cookie生效時間30天 ,單位秒;-->
        simpleCookie.setMaxAge(259200);
        return simpleCookie;
    }
    /**
     * cookie管理對象;
     * 
     * @return
     */
    @Bean(name = "rememberMeManager")
    public CookieRememberMeManager rememberMeManager() {
        logger.info("ShiroConfiguration.rememberMeManager()");
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        return cookieRememberMeManager;
    }
    /**
     * SecurityManager,權限管理,這個類組合了登陸,登出,權限,session的處理,是個比較重要的類。
     * 
     * @return
     */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager securityManager() {
        logger.info("ShiroConfiguration.getDefaultWebSecurityManager()");
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 設置realm.
        securityManager.setRealm(myShiroRealm());
        // <!-- 用戶授權/認證信息Cache, 采用EhCache 緩存 -->
        securityManager.setCacheManager(ehCacheManager());
        //注入記住我管理器;  
        securityManager.setRememberMeManager(rememberMeManager());  
        return securityManager;
    }

    /**
     * ShiroFilterFactoryBean,是個factorybean,為了生成ShiroFilter。
     * 它主要保持了三項數據,securityManager,filters,filterChainDefinitionManager。
     * 
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter() {
        logger.info("ShiroConfiguration.shiroFilter()");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 必須設置SecuritManager
        shiroFilterFactoryBean.setSecurityManager(securityManager());

        Map<String, Filter> filtersMap = shiroFilterFactoryBean.getFilters();
        filtersMap.put("authc", myFormAuthenticationFilter());// 自定義攔截器
        shiroFilterFactoryBean.setFilters(filtersMap);

        // 攔截器
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        // 配置退出過濾器,其中的具體代碼Shiro已經替我們實現了
        filterChainDefinitionMap.put("/logout", "logout");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        // <!-- 過濾鏈定義,從上向下順序執行,一般將 /**放在最為下邊 -->:這是一個坑呢,一不小心代碼就不好使了;
        // <!-- authc:所有url都必須認證通過才可以訪問; anon:所有url都都可以匿名訪問-->
        filterChainDefinitionMap.put("/logout", "logout");
        filterChainDefinitionMap.put("/index", "authc");
        filterChainDefinitionMap.put("/**", "authc");

        // 如果不設置默認會自動尋找工程根目錄下的"/login"頁面
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 登錄成功后要跳轉的鏈接
        shiroFilterFactoryBean.setSuccessUrl("/index");
        // 未授權界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        // 加載shiroFilter權限控制規則
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;

    }

    @Bean
    public MyFormAuthenticationFilter myFormAuthenticationFilter() {
        MyFormAuthenticationFilter myFormAuthenticationFilter = new MyFormAuthenticationFilter();
        return myFormAuthenticationFilter;
    }

    /**
     * DefaultAdvisorAutoProxyCreator,Spring的一個bean,由Advisor決定對哪些類的方法進行AOP代理。
     * 
     * @return
     */
    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        logger.info("ShiroConfiguration.defaultAdvisorAutoProxyCreator()");
        DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
        daap.setProxyTargetClass(true);
        return daap;
    }

    /**
     * AuthorizationAttributeSourceAdvisor,shiro里實現的Advisor類,
     * 內部使用AopAllianceAnnotationsAuthorizingMethodInterceptor來攔截用以下注解的方法。
     * 老實說,這里注入securityManager,我不知道有啥用,從source上看不出它在什么地方會被調用。
     * 
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        logger.info("ShiroConfiguration.authorizationAttributeSourceAdvisor()");
        AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
        aasa.setSecurityManager(securityManager());
        return aasa;
    }
    /**
     * ShiroDialect,為了在thymeleaf里使用shiro的標簽的bean
     * 
     * @return
     */
    @Bean(name = "shiroDialect")
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }
}

thymleaf使用shiro標簽,需要引入

        <dependency>  
            <groupId>com.github.theborakompanioni</groupId>  
            <artifactId>thymeleaf-extras-shiro</artifactId>  
            <version>1.2.1</version>  
        </dependency>  

 

注:問題:https://www.oschina.net/question/250720_195683

FilterChain修改如下:

        // 攔截器
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        // <!-- 過濾鏈定義,從上向下順序執行,一般將 /**放在最為下邊 -->:這是一個坑呢,一不小心代碼就不好使了;
        // <!-- authc:所有url都必須認證通過才可以訪問; anon:所有url都都可以匿名訪問-->
        // 配置退出過濾器,其中的具體代碼Shiro已經替我們實現了    
        filterChainDefinitionMap.put("/", "authc");
        filterChainDefinitionMap.put("/index", "authc");
        filterChainDefinitionMap.put("/logout", "logout");
        //filterChainDefinitionMap.put("/**", "anon");    
        filterChainDefinitionMap.put("/sys/**", "authc");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/images/**", "anon");
        filterChainDefinitionMap.put("/vendors/**", "anon");
        filterChainDefinitionMap.put("/fonts/**", "anon");
        // 加載shiroFilter權限控制規則
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

 

參考博客:Apache Shiro和Spring boot的結合使用

參考博客:Spring Boot Shiro 權限信息緩存處理,記住我,thymleaf使用shiro標簽

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM