最近公司開發一個微信小程序項目加shiro的項目。因為微信小程序是不使用cookie,使用的是 storage 。那么我們就不能使用傳統的方式來保持登錄狀態了。
1.首先和網上的一樣,先重寫一個Session管理器
public class MySessionManager extends DefaultWebSessionManager { private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request"; @Override protected Serializable getSessionId(ServletRequest request, ServletResponse response) { System.out.println("執行session管理器>>>>>>>>>>>>>>>>>>>>>>>>"); String id = WebUtils.toHttp(request).getHeader("TOKEN"); if(StringUtils.isEmpty(id)){ //如果沒有攜帶id參數則按照父類的方式在cookie進行獲取 return super.getSessionId(request, response); }else{ //如果請求頭中有 token 則其值為sessionId request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,REFERENCED_SESSION_ID_SOURCE); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID,id); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID,Boolean.TRUE); return id; } } }
2.將自定義的session管理器交給spring管理
@Configuration public class ShiroConfig { @Bean public DefaultWebSecurityManager securityManager(){ DefaultWebSecurityManager manager = new DefaultWebSecurityManager(); manager.setRealm(realm()); manager.setSessionManager(defaultWebSessionManager()); return manager; } @Bean public DefaultWebSessionManager defaultWebSessionManager(){ MySessionManager manager = new MySessionManager(); return manager; } ...... }
到這里看樣子似乎是沒有什么事情了,但是事與願違,因為我登陸成功之后,每次都被登錄過濾器給攔截了。這是為啥嘞?
經過幾輪的debug調試才發現,原來在調用完之后 getSessionId方法之后會有一個設置過期時間的過程(當然這個很正常),默認給設置的是1800,剛開始我覺得沒什么毛病啊。就沒理他,可是繼續往下debug的時候發現報錯信息竟然是回話已超時,之后就被登錄過濾器給定義為登錄失敗了(囧)。話說不是已經設置了默認的過期時間了嗎? 然后我不服,重寫了設置過期時間的方法
@Override public void setTimeout(SessionKey key, long maxIdleTimeInMillis) throws InvalidSessionException { super.setTimeout(key, 3600000); }
結果就好了。一定要仔細看第二個參數 maxIdleTimeInMillis 這是最大過期時間的毫秒值啊!!!默認給個1800,不就是1.8秒嗎?那這樣的話想要讓這個回話不過期只能自己設置一個比較大的過期時間了,或者你可以做這時間上最快的男人每1.8秒內就請求一次,這樣shiro就會重置過期時間。