1. 程式人生 > >shiro多Realm第一次呼叫不生效問題

shiro多Realm第一次呼叫不生效問題

1. 由於最近自己寫的一個專案上用到了多realm的使用,遇到了一個這樣的問題:

  1. 自己繼承了BasicHttpAuthenticationFilter,實現了獲取token,然後直接請求api的方法,但是每次第一次呼叫的時候都是無效的,第二次請求又是正常的。

以下為配置檔案

    @Bean
    public ShiroFilterFactoryBean shirFilter(org.apache.shiro.mgt.SecurityManager securityManager) {
        logger.debug("ShiroConfiguration.shiroFilter()");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //攔截器.
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        // 配置不會被攔截的連結 順序判斷
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/fonts/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/index.html", "anon");
        filterChainDefinitionMap.put("/login.html", "anon");
        filterChainDefinitionMap.put("/register.html", "anon");
        //配置退出 過濾器,其中的具體的退出程式碼Shiro已經替我們實現了
        filterChainDefinitionMap.put("/auth/logout", "logout");
        filterChainDefinitionMap.put("/auth/login", "anon");
        filterChainDefinitionMap.put("/wx/app/login/**", "anon");
        filterChainDefinitionMap.put("/auth/register", "anon");
        //<!-- 過濾鏈定義,從上向下順序執行,一般將/**放在最為下邊 -->:這是一個坑呢,一不小心程式碼就不好使了;
        //<!-- authc:所有url都必須認證通過才可以訪問; anon:所有url都都可以匿名訪問-->
        filterChainDefinitionMap.put("/**", "authc,token");
        // 如果不設定預設會自動尋找Web工程根目錄下的"/login.jsp"頁面
        //配置shiro預設登入介面地址,前後端分離中登入介面跳轉應由前端路由控制,後臺僅返回json資料
        shiroFilterFactoryBean.setLoginUrl("/unauth");
        // 登入成功後要跳轉的連結
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //未授權介面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        Map<String,Filter> filterMap=new HashedMap();
        filterMap.put("token",headerHttpAuthenticationFilter());
        shiroFilterFactoryBean.setFilters(filterMap);
        return shiroFilterFactoryBean;
    }

  2. 貼出主要的配置檔案

2.分析問題:

  1. 由於第一次不正常,第二次正常,又因為shiro的許可權認證是根據sessionId+過濾器實現的,每次刪除sessionId的cookie後,第一次通過token方式進行請求都會出現沒有許可權的問題。

  2. 檢查HeaderHttpAuthenticationFilter類發現正常,在該類中打斷點,發現方法能夠正常進入到該方法中,並且是正常的

      3. 查詢shiro中的Filter呼叫鏈,發現ProxiedFilterChain類中是這樣進行呼叫的

   

    public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
        if (this.filters != null && this.filters.size() != this.index) {
            if (log.isTraceEnabled()) {
                log.trace("Invoking wrapped filter at index [" + this.index + "]");
            }

            ((Filter)this.filters.get(this.index++)).doFilter(request, response, this);
        } else {
            if (log.isTraceEnabled()) {
                log.trace("Invoking original filter chain.");
            }

            this.orig.doFilter(request, response);
        }

    }

  獲取filters然後進行一個一個呼叫,查詢以及跟蹤斷點發現,authc該方式中對應的為BasicHttpAuthenticationFilter

在BasicHttpAuthenticationFilter打上斷點

發現每次會請求到該方法上,查詢原因發現,由於我是token請求,並沒有帶該引數導致的

 

問題解決:

  1. 檢視ShiroConfig類中發現

        filterChainDefinitionMap.put("/**", "authc,token");

  位置放置許可權filter鑑權有問題,由於token的鑑權會比authc的許可權高,自定義許可權比普通的表單認證的優先順序高。所以應該將其放到前面,修改為如下

 

        filterChainDefinitionMap.put("/**", "token,authc");

  2. 重啟專案,執行正常了