Shiro筆記七:自定義Shiro Filter過濾器

Shiro筆記七:自定義Shiro Filter過濾器

shiro自帶的Filter的問題

  1. shiro有自帶的過濾器在DefaultFilter裏面,但是有個問題。

filterChainDefinitionMap.put("/admin/**",“roles[admin,root]”);//中括號裏面的是角色的名字

這裏面的問題是:只有當用戶屬於admin和root角色時,才能訪問這個路徑,如果只有root角色或者只有admin角色,是不能訪問的。相當於hasAllRole()

  1. 現在的需求是:只需要有其中一個角色就能滿足訪問。這就需要自定義Filter

自定義Filter,繼承AuthorizationFilter,重寫裏面的isAccessAllowed方法。

public class CustomRolesOrAuthorizationFilter extends AuthorizationFilter {

    public CustomRolesOrAuthorizationFilter(){

    }

    @Override
    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
        Subject subject = this.getSubject(request, response);
        //獲取當前訪問路徑所需要的角色集合
        String[] rolesArray = (String[])((String[])mappedValue);
        if (rolesArray != null && rolesArray.length != 0) {
            Set<String> roles = CollectionUtils.asSet(rolesArray);
            //當前subject是roles中的任意一個,則有權訪問。
            for(String role:roles){
                if(subject.hasRole(role)){
                    return true;
                }
            }
            return false;
        } else {
            return true;
        }
    }
}
  1. 修改調用的過濾器鏈
filterChainDefinitionMap.put("/admin/**","roleOrFilter[admin,root]");//中括號裏面的是角色的名字。

使用Redis整合CacheManager

  1. 使用redis原因

授權的時候每次都去查詢數據庫,對於頻繁訪問接口,性能和響應速度比較慢,使用緩存代替之。

  1. 解決方案:

一是:在業務代碼查詢數據庫的時候,添加進程緩存。

二是:使用Redis緩存。

  1. 使用Redis緩存步驟:

1、添加依賴,shiro+redis的緩存插件

<!-- shiro+redis緩存插件 -->
<dependency>
    <groupId>org.crazycake</groupId>
    <artifactId>shiro-redis</artifactId>
    <version>3.1.0</version>
</dependency>
  1. 編寫redis配置類
/**
     * 配置RedisManager
     * @return
     */
public RedisManager getRedisManager(){

    RedisManager redisManager=new RedisManager();
    redisManager.setHost("localhost");
    redisManager.setPort(6379);
    redisManager.setDatabase(1);
    return redisManager;

}
  1. 將Redis配置整合到Shiro的CacheManager
/**
     * 配置CacheManager的具體實現類
     * @return
     */
public RedisCacheManager cacheManager(){//RedisCacheManager實現了CacheManager的接口
    RedisCacheManager redisCacheManager=new RedisCacheManager();
    redisCacheManager.setRedisManager(getRedisManager());
    //設置過期時間20s
    redisCacheManager.setExpire(20);
    return redisCacheManager;

}

4、讓整合redis的cacheManager作爲shiro的緩存方案。在SecurityManager裏面配置

@Bean
public SecurityManager securityManager(){
    DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
    securityManager.setSessionManager(sessionManager());
    //使用自定義的cacheManager
    securityManager.setCacheManager(cacheManager());//此處添加緩存配置。
    //推薦放到最後,不然某些版本不生效
    securityManager.setRealm(customRealm());

    return securityManager;
}

使用Redis整合SessionManager

  1. 爲什麼要對Session持久化

重啓應用,用戶無感知,可以繼續以原先的狀態繼續訪問。

  1. 持久化

1、使用Redis持久化,結合Shiro的RedisSessionDAO進行持久化

2、使用RedisSessionDAO加載Redis組件。

3、使用SessionManager加載RedisSessionDao。

4、注意實體類要進行序列化

/**
     * 自定義redis持久化
     * @return
     */
public RedisSessionDAO redisSessionDAO(){
    RedisSessionDAO redisSessionDAO=new RedisSessionDAO();
    redisSessionDAO.setRedisManager(getRedisManager());
    redisSessionDAO.setExpire(20);
    return redisSessionDAO;
}

SessionManager加載RedisSessionDao

/**
     * 設置會話,自定義Session
     * @return
     */
@Bean
public SessionManager sessionManager(){
    CustomSessionManager customSessionManager=new CustomSessionManager();
    //設置會話超時時間,單位是毫秒,默認是30分鐘
    //customSessionManager.setGlobalSessionTimeout(200000);
    //配置session持久化
    customSessionManager.setSessionDAO(redisSessionDAO());
    return customSessionManager;
}

ShiroConfig中常用Bean類配置

  1. LifecycleBeanPostProcessor

作用:管理shiro一些bean的生命週期 即bean初始化 與銷燬,注意管理的只是Shiro的Bean.

/**
     * 作用:管理shiro一些bean的生命週期 即bean初始化 與銷燬
     * @return
     */
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
    return new LifecycleBeanPostProcessor();
}
  1. AuthorizationAttributeSourceAdvisor

作用:加入註解的使用,不加入這個AOP註解不生效(shiro的註解 例如 @RequiresGuest)

/**
     * 作用:加入註解的使用,不加入這個AOP註解不生效(shiro的註解 例如 @RequiresGuest)
     * @return
     */
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
    return authorizationAttributeSourceAdvisor;
}

  1. DefaultAdvisorAutoProxyCreator

作用: 用來掃描上下文尋找所有的Advistor(通知器), 將符合條件的Advisor應用到切入點的Bean中,需
要在LifecycleBeanPostProcessor創建後纔可以創建

/**
     * 作用: 用來掃描上下文尋找所有的Advistor(通知器), 將符合條件的Advisor應用到切入點的Bean中,需
     * 要在LifecycleBeanPostProcessor創建後纔可以創建
     * @return
     */
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    defaultAdvisorAutoProxyCreator.setUsePrefix(true);
    return defaultAdvisorAutoProxyCreator;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章