禁用Cookie后,Session怎么样使用
轉(zhuǎn)載自??禁用Cookie后,Session怎么樣使用
在上篇中更多的是在分析通過Session Cookie這一方式,在每次請(qǐng)求時(shí)都將
sessionId以Cookie的形式發(fā)到服務(wù)端,來保持一致。這也是許多人印象中的
Session在瀏覽器關(guān)閉之后就失效這一說法的來源。
其實(shí)本質(zhì)上是瀏覽器在關(guān)閉之后,應(yīng)用對(duì)應(yīng)的SessionCookie被清除了,再次打開瀏覽器請(qǐng)求應(yīng)用時(shí),之前的SessionId對(duì)應(yīng)的Cookie不存在,所以就會(huì)重新創(chuàng)建一個(gè)Session。而服務(wù)端原來的Session其實(shí)還是存在的,只是沒人與之對(duì)應(yīng),就默默的等著超時(shí)時(shí)間一到,被清除了。
而對(duì)于Cookie,我們都知道其是瀏覽器保存客戶端本地的,安全問題暫且不說,但Cookie是可以在瀏覽器中配置后關(guān)閉的。關(guān)閉之后,服務(wù)器就不能再向?yàn)g覽器寫Cookie的,此時(shí)我們基于SessionCookie的實(shí)現(xiàn)方式就遇到了問題。
雖然每一次仍然通過response將Set-Cookie添加到header里,但發(fā)到瀏覽器的時(shí)候,不能再寫Cookie,后續(xù)的請(qǐng)求依然是重新發(fā)一個(gè)sessionId為null的請(qǐng)求,導(dǎo)致每次仍是重新創(chuàng)建session對(duì)象,并沒有解決交互狀態(tài)的問題。
為了解決這個(gè)問題,服務(wù)器提供了另外一種方式:
URL重寫,即英文的URLrewrite。
這一方式,其本質(zhì)上是在每次請(qǐng)求的url后面append 上一個(gè)類似于jsessionid=xxxx這樣的參數(shù),在服務(wù)端解析時(shí),獲取到j(luò)sessionid對(duì)應(yīng)的值,并根據(jù)其獲取到對(duì)應(yīng)的Session對(duì)象,從而保證了交互狀態(tài)一致。
一句話就說明白了。
但這一句話背后,有一些事情還是需要注意的,
例如,我們可以自己在url后面寫上jsessionid=當(dāng)前session的id值。這種類似于硬編碼,因?yàn)榉?wù)端獲取這個(gè)session的id是通過jsessionid這個(gè)參數(shù)名來獲取的,而這個(gè)參數(shù)我們?cè)谇耙黄恼轮辛私獾?#xff0c;是可以配置的,當(dāng)改了之后,后面的sessionId就獲取不到了。
其次,為了保證各類url規(guī)則的一致,服務(wù)端提供了response API來處理,只需要直接使用,就可以完成jsessionid的參數(shù)追加。
我們看代碼中的實(shí)現(xiàn)邏輯:
/*** Return <code>true</code> if the specified URL should be encoded with* a session identifier. This will be true if all of the following* conditions are met:* <ul>* <li>The request we are responding to asked for a valid session* <li>The requested session ID was not received via a cookie* <li>The specified URL points back to somewhere within the web* application that is responding to this request* </ul>** @param location Absolute URL to be validated*/ protected boolean isEncodeable(final String location) {if (location == null) {return (false);}// Is this an intra-document reference?if (location.startsWith("#")) {return (false);}// Are we in a valid session that is not using cookies?final Request hreq = request;final Session session = hreq.getSessionInternal(false);if (session == null) {return (false);}if (hreq.isRequestedSessionIdFromCookie()) {return (false);}// Is URL encoding permittedif (!hreq.getServletContext().getEffectiveSessionTrackingModes().contains(SessionTrackingMode.URL)) {return false;}return doIsEncodeable(hreq, session, location);}代碼中會(huì)根據(jù)是否使用SessionCookie來決定是否要繼續(xù),
之后會(huì)繼承判斷可使用的Session tracking Mode里都有哪些,是否包含URL。
在doIsEncodeable方法中,最終實(shí)現(xiàn)是這一行代碼
String tok = ";" +SessionConfig.getSessionUriParamName(request.getContext()) +"=" + session.getIdInternal();也就是我們上面提到的硬編碼jsessionid到url后面不太好的原因,這里就是在讀取它的配置。
public static String getSessionUriParamName(Context context) {String result = getConfiguredSessionCookieName(context);if (result == null) {result = DEFAULT_SESSION_PARAMETER_NAME;}return result;}另外,我們上面提到的Session tracking Mode,是在Tomcat啟動(dòng)的時(shí)候判斷的,而服務(wù)端并不可能得知以后要連接的瀏覽器中,哪些是不允許Cookie的,所以對(duì)于Sesion tracking mode,URL無(wú)論如何都是可以使用的,而Session cookie是否要使用,是通過在Context組件中配置的其cookies屬性為false時(shí)禁止的
private void populateSessionTrackingModes() {
// URL re-writing is always enabled by default
defaultSessionTrackingModes = EnumSet.of(SessionTrackingMode.URL);
supportedSessionTrackingModes = EnumSet.of(SessionTrackingMode.URL);
if (context.getCookies())?{ //此處讀取Context組件的cookies配置,如果為false,則不使用SessionCookie
defaultSessionTrackingModes.add(SessionTrackingMode.COOKIE);
supportedSessionTrackingModes.add(SessionTrackingMode.COOKIE);?}
?
總結(jié)下,即為了防止客戶端禁用Cookie導(dǎo)致的Session狀態(tài)不一致的情況,我們可以采用UrlRewrite的方式來保證。
這一過程,我們可以使用response的encodeURL方法來使sessionid添加到url后面,不過是需要先在Context組件中聲明不使用cookies。
?
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的禁用Cookie后,Session怎么样使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面试官问:如果MySQL引起CPU消耗过
- 下一篇: Zookeeper超详细的面试题