日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Apache Shiro去掉URL中的JSESSIONID

發(fā)布時(shí)間:2025/3/15 javascript 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Apache Shiro去掉URL中的JSESSIONID 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

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

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

先說下為什么網(wǎng)上那些玩意沒用。

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

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

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

ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE。這就是為什么我們刪掉JSESSIONID他又不加上的原因。因?yàn)槟愫竺婷看卧L問。構(gòu)建subject的時(shí)候sessionid有值request的里面也有值他就不會在url上加JSESSIONID了啊。假設(shè)我們刪除瀏覽器cookie這個(gè)時(shí)候沒有了sessionid。我們訪問當(dāng)前地址。同樣會創(chuàng)建Subject。由于sessionid沒有了所以request里面就不會存值了。然后會進(jìn)入org.apache.shiro.web.filter.authc.UserFilter判斷subject是否有認(rèn)證信息。沒有會通過saveRequestAndRedirectToLogin跳轉(zhuǎn)到登陸頁面。saveRequestAndRedirectToLogin里面判斷request是否有值沒值又會在跳轉(zhuǎn)頁面的url上加上JSESSIONID。然后進(jìn)入登陸界面的時(shí)候構(gòu)建subject
創(chuàng)建session request里面存值。好了說完了。看不懂得自己腦補(bǔ)把。

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);}}

我的辦法在每次跳轉(zhuǎn)之前就判斷sessionid是否有值。因?yàn)槊看翁D(zhuǎn)之前subject就已經(jīng)創(chuàng)建了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版本以上這個(gè)BUG已經(jīng)解決只需要在配置文件如下配置中添加紅色部分

<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"><!-- 設(shè)置這個(gè)屬性就可以解決問題--> <property name="sessionIdUrlRewritingEnabled" value="false" /><!-- 驗(yàn)證會話時(shí)會話的過期時(shí)間(毫秒) --><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());

文章轉(zhuǎn)自

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。