首先我們看Shiro的會話管理器的配置
<!-- shiro會話管理 --> <!-- 即用戶登錄后就是一次會話,在沒有退出之前,它的所有信息都在會話中;會話可以是普通 JavaSE 環境的,也可以是如 Web 環境的 --> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <property name="cacheManager" ref="redisCacheManager"/> <property name="sessionDAO" ref="redisSessionDAO"/> <!-- <property name="sessionIdCookie" ref="simpleCookie"/> --> <!-- 全局的會話信息時間,,單位為毫秒 --> <property name="globalSessionTimeout" value="1800000"/> <!-- 檢測掃描信息時間間隔,單位為毫秒--> <property name="sessionValidationInterval" value="60000"/> <!-- 是否開啟掃描 --> <property name="sessionValidationSchedulerEnabled" value="false"/> <!-- 去掉URL中的JSESSIONID --> <property name="sessionIdUrlRewritingEnabled" value="true"/> </bean>
這里是使用DefaultWebSessionManager默認的Cookie配置
部分源代碼
public class DefaultWebSessionManager extends DefaultSessionManager implements WebSessionManager { private static final Logger log = LoggerFactory.getLogger(DefaultWebSessionManager.class); private Cookie sessionIdCookie; private boolean sessionIdCookieEnabled; private boolean sessionIdUrlRewritingEnabled; public DefaultWebSessionManager() { Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME); cookie.setHttpOnly(true); //more secure, protects against XSS attacks this.sessionIdCookie = cookie; this.sessionIdCookieEnabled = true; this.sessionIdUrlRewritingEnabled = true; } }
這里可以看出Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);內部默認創建了一個Cookie。
繼續看
public SimpleCookie(String name) { this(); this.name = name; }
而ShiroHttpSession.DEFAULT_SESSION_ID_NAME="JSESSIONID";
問題來了--》Session失效問題這里為什么為導致Session失效呢?
因為與SERVLET容器名沖突, 如JETTY, TOMCAT 等默認JSESSIONID, 當跳出SHIRO SERVLET時如ERROR-PAGE容器會為JSESSIONID重新分配值導致登錄會話丟失效。
因此這里需要自己配置Cookie
<!-- shiro會話管理 --> <!-- 即用戶登錄后就是一次會話,在沒有退出之前,它的所有信息都在會話中;會話可以是普通 JavaSE 環境的,也可以是如 Web 環境的 --> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <property name="cacheManager" ref="redisCacheManager"/> <property name="sessionDAO" ref="redisSessionDAO"/> <property name="sessionIdCookie" ref="simpleCookie"/> <!-- 全局的會話信息時間,,單位為毫秒 --> <property name="globalSessionTimeout" value="1800000"/> <!-- 檢測掃描信息時間間隔,單位為毫秒--> <property name="sessionValidationInterval" value="60000"/> <!-- 是否開啟掃描 --> <property name="sessionValidationSchedulerEnabled" value="false"/> <!-- 去掉URL中的JSESSIONID --> <property name="sessionIdUrlRewritingEnabled" value="true"/> </bean> <!-- sessionIdCookie的實現,用於重寫覆蓋容器默認的JSESSIONID --> <bean id="simpleCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <!-- 設置Cookie名字, 默認為: JSESSIONID 問題: 與SERVLET容器名沖突, 如JETTY, TOMCAT 等默認JSESSIONID, 當跳出SHIRO SERVLET時如ERROR-PAGE容器會為JSESSIONID重新分配值導致登錄會話丟失! --> <property name="name" value="SHIRO-COOKIE"/> <!-- JSESSIONID的path為/用於多個系統共享JSESSIONID --> <!-- <property name="path" value="/"/> --> <!-- 瀏覽器中通過document.cookie可以獲取cookie屬性,設置了HttpOnly=true,在腳本中就不能的到cookie,可以避免cookie被盜用 --> <property name="httpOnly" value="true"/> </bean>
好了,這里Shiro配置Cookie就完成了。
此外,如果要配置多個系統共享Session,放開Cookie中的注釋即可。
<!-- sessionIdCookie的實現,用於重寫覆蓋容器默認的JSESSIONID --> <bean id="simpleCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <!-- 設置Cookie名字, 默認為: JSESSIONID 問題: 與SERVLET容器名沖突, 如JETTY, TOMCAT 等默認JSESSIONID, 當跳出SHIRO SERVLET時如ERROR-PAGE容器會為JSESSIONID重新分配值導致登錄會話丟失! --> <property name="name" value="SHIRO_COOKIE"/> <!-- JSESSIONID的path為/用於多個系統共享JSESSIONID --> <property name="path" value="/"/> <!-- 瀏覽器中通過document.cookie可以獲取cookie屬性,設置了HttpOnly=true,在腳本中就不能的到cookie,可以避免cookie被盜用 --> <property name="httpOnly" value="true"/> </bean>
這樣多個系統就能共享Session了。
