日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Apache Shiro去掉URL中的JSESSIONID

發布時間:2025/3/15 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Apache Shiro去掉URL中的JSESSIONID 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近集成框架用到shiro碰到url有時候會帶上jsessionid有時候又沒有。以前也碰到但是沒有深入研究。

網上查了半天各種方法用了都沒用。比如web.xml里面加session-config,添加DisableUrlSessionFilter 等等神馬都沒用。于是自己研究源碼。說了半天廢話終于進入正題。先申明下我是菜鳥。說的不對的錯的請無視。有些是網上復制的。

先說下為什么網上那些玩意沒用。

我們一般用的是DefaultWebSessionManager。shiro默認的是ServletContainerSessionManager這個非常簡單的實現代表所有會話管理職責(包括會話集群如果
servlet 容器支持)運行 servlet 容器。 它本質上是一個橋 Shiro 會話 API 的 servlet
容器,沒有別的。使用這個默認的一個好處是,使用現有的 servlet
容器的應用程序會話配置(超時,任何特定容器集群機制等)將正常工作。這個默認的缺點是,你與 servlet 容器的特定會話行為。
舉個例子,如果你想集群會話,但你使用 Jetty 在生產、測試和 Tomcat
容器配置(或代碼)將不具有可移植性。所以我們用DefaultWebSessionManager Shiro
的原生會話管理。所以網上的那些基于servlet
的不起作用。如果你用ServletContainerSessionManager也不存在這個問題。(后續有時間我會說說shiro和redis的集成。用redis管理session和cache。我是看了spring
session、spring data redis的源碼改造的所以跟spring能很好的集成具體后面再說。

下面分析源碼。先說下shiro的每次訪問都會構建subject。

假設我們首次訪問系統的登陸界面。然后我們登陸。在我們點擊登陸之后會訪問DefaultSecurityManager構建Subject。創建Subject之前會做很多事(創建cookie和session等等)其中會訪問一下DefaultWebSessionManager的getReferencedSessionId方法。方法里面判斷cookie里面是否有sessionid??隙ㄊ菦]有的啦所以不會向request里面存放ShiroHttpServletRequest的3個靜態屬性。然后在org.apache.shiro.web.filter.authc.FormAuthenticationFilter登陸成功跳轉頁面的時候。issueSuccessRedirect方法里面會判斷request是否有ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE如果有直接跳轉到成功頁面。具體判斷的代碼在ShiroHttpServletRequest里面的isRequestedSessionIdFromURL方法上。如果沒有會在跳轉成功頁面url后面加上JSESSIONID。所以url上就多出了JSESSIONID.然后跳轉首頁時又會訪問DefaultSecurityManager構建Subject。同樣會進DefaultWebSessionManager的getReferencedSessionId方法這個時候sessionid有值所以request里面存放了

ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE。這就是為什么我們刪掉JSESSIONID他又不加上的原因。因為你后面每次訪問。構建subject的時候sessionid有值request的里面也有值他就不會在url上加JSESSIONID了啊。假設我們刪除瀏覽器cookie這個時候沒有了sessionid。我們訪問當前地址。同樣會創建Subject。由于sessionid沒有了所以request里面就不會存值了。然后會進入org.apache.shiro.web.filter.authc.UserFilter判斷subject是否有認證信息。沒有會通過saveRequestAndRedirectToLogin跳轉到登陸頁面。saveRequestAndRedirectToLogin里面判斷request是否有值沒值又會在跳轉頁面的url上加上JSESSIONID。然后進入登陸界面的時候構建subject
創建session request里面存值。好了說完了。看不懂得自己腦補把。

private Serializable getReferencedSessionId(ServletRequest request, ServletResponse response) {String id = getSessionIdCookieValue(request, response);if (id != null) {request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);} else {//not in a cookie, or cookie is disabled - try the request URI as a fallback (i.e. due to URL rewriting)://try the URI path segment parameters first:id = getUriPathSegmentParamValue(request, ShiroHttpSession.DEFAULT_SESSION_ID_NAME);if (id == null) {//not a URI path segment parameter, try the query parameters:String name = getSessionIdName();id = request.getParameter(name);if (id == null) {//try lowercase:id = request.getParameter(name.toLowerCase());}}if (id != null) {request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,ShiroHttpServletRequest.URL_SESSION_ID_SOURCE);}} public boolean isRequestedSessionIdFromURL() {if (isHttpSessions()) {return super.isRequestedSessionIdFromURL();} else {String value = (String) getAttribute(REFERENCED_SESSION_ID_SOURCE);return value != null && value.equals(URL_SESSION_ID_SOURCE);}}

我的辦法在每次跳轉之前就判斷sessionid是否有值。因為每次跳轉之前subject就已經創建了session。至于如果禁用cookies。同樣還是會在url上加上jsessionid。我們只是把判斷給至前了。并沒有修改原有邏輯。具體代碼如下

/*** clear JSESSIONID in URL if session id is not null * {@link DefaultWebSessionManager} getReferencedSessionId* {@link ShiroHttpServletRequest} isRequestedSessionIdFromURL* * @author Infinite Justice*/ public class UserFilter extends AccessControlFilter{private Cookie sessionIdCookie;public Cookie getSessionIdCookie() {return sessionIdCookie;}public void setSessionIdCookie(Cookie sessionIdCookie) {this.sessionIdCookie = sessionIdCookie;}@Overrideprotected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {if (isLoginRequest(request, response)) {return true;} else {Subject subject = getSubject(request, response);// If principal is not null, then the user is known and should be allowed access.return subject.getPrincipal() != null;}}@Overrideprotected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {saveRequest(request);String sessionid = sessionIdCookie.readValue(WebUtils.toHttp(request), WebUtils.toHttp(response));// clear JSESSIONID in URL if session id is not null if(sessionid != null){request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sessionid);request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);}redirectToLogin(request, response);return false;} } /*** clear JSESSIONID in URL if session id is not null * {@link DefaultWebSessionManager} getReferencedSessionId* {@link ShiroHttpServletRequest} isRequestedSessionIdFromURL* * @author Infinite Justice*/ public class LoginFilter extends FormAuthenticationFilter{private Cookie sessionIdCookie;public Cookie getSessionIdCookie() {return sessionIdCookie;}public void setSessionIdCookie(Cookie sessionIdCookie) {this.sessionIdCookie = sessionIdCookie;}@Overrideprotected void setFailureAttribute(ServletRequest request, AuthenticationException ae) {request.setAttribute(getFailureKeyAttribute(), ae);}@Overrideprotected void issueSuccessRedirect(ServletRequest request, ServletResponse response) throws Exception {String sessionid = sessionIdCookie.readValue(WebUtils.toHttp(request), WebUtils.toHttp(response));// clear JSESSIONID in URL if session id is not null if(sessionid != null){request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sessionid);request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);}super.issueSuccessRedirect(request, response);} }

另一種解決辦法:

public class RedisWebSessionManager extends DefaultWebSessionManager {/*** Stores the Session's ID, usually as a Cookie, to associate with future requests.* @param session the session that was just{@link #createSession created}.*/@Overrideprotected void onStart(Session session, SessionContext context) {super.onStart(session, context);ServletRequest request = WebUtils.getRequest(context);request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);}}

——————————————————————————————黃金分割線————————————————————————————————————————

如果你的shiro版本在1.3.2版本以上這個BUG已經解決只需要在配置文件如下配置中添加紅色部分

<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"><!-- 設置這個屬性就可以解決問題--> <property name="sessionIdUrlRewritingEnabled" value="false" /><!-- 驗證會話時會話的過期時間(毫秒) --><property name="globalSessionTimeout" value="3600000" /><property name="sessionFactory" ref="sessionFactory" /><property name="sessionValidationScheduler" ref="redisValidationScheduler" /><property name="sessionDAO" ref="sessionDAO" /><property name="sessionIdCookie" ref="sessionIdCookie" /><property name="sessionListeners"><list><ref bean="redisSessionListener" /></list></property></bean>

源代碼中的解釋如下

// always set rewrite flag - SHIRO-361request.setAttribute(ShiroHttpServletRequest.SESSION_ID_URL_REWRITING_ENABLED, isSessionIdUrlRewritingEnabled());

文章轉自

總結

以上是生活随笔為你收集整理的Apache Shiro去掉URL中的JSESSIONID的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。