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. 重啟專案,執行正常了