会话Cookie及session的关系(Cookie Session)
會話Cookie及session的關系(Cookie & Session)
在通常的使用中,我們只知道session信息是存放在服務器端,而cookie是存放在客戶端。但服務器如何使用session和客戶端之間進行通信,以及jsessionId是怎么回事,這并沒有一個完整和正確的認識,因此這里將這類信息匯總。
session中的jsessionId是在session創(chuàng)建好之后,發(fā)送給客戶端。然后在每一次請求中,客戶端即會將這個信息傳遞給服務器端,服務器端使用這個信息來維護和客戶端之間的會話通信,在瀏覽器關閉之后,這個session就消失了。
而對于普通的cookie來說,它是有著一定的時間存放在客戶端的機器中的。當下次打開瀏覽器時,這個cookie就會被讀取,同時在請求時發(fā)放到服務器端。在關閉瀏覽器,這個cookie仍然存在的,并沒有消失。
那么,這兩者之間有沒有聯(lián)系呢,這就要看官方對于Cookie的不同分類,其實就對應著session Cookie和psersistent Cookie的描述了。如下所示:
Session Cookie
A user's session cookie[15] (also known as an in-memory cookie or transient cookie) for a website exists in temporary memory only while the user is reading and navigating the website. When an expiry date or validity interval is not set at cookie creation time, a session cookie is created. Web browsers normally delete session cookies when the user closes the browser.
Persistent cookie
A persistent cookie[15] will outlast user sessions. If a persistent cookie has its Max-Age set to 1 year (for example), then, during that year, the initial value set in that cookie would be sent back to the server every time the user visited the server. This could be used to record a vital piece of information such as how the user initially came to this website. For this reason, persistent cookies are also called tracking cookies.
從上面的描述中看,所謂的session Cookie,就是我們所說的session,其實就是一個沒有設置過期時間的cookie信息。而普通的cookie,即我們通常所說的cookie,就是設置了過期時間(有效時間,通常大于一個特定的值,如一周)的cookie。
那么,我們可以這樣認為。session就是服務器端,通過使用session Cookie來維系客戶端和服務器的關系,而所謂的存儲就是在服務器端針對這個session值(如jsessionId值)作了一個內部的增強,可以圍繞著這個session Cookie創(chuàng)建一個單獨的數(shù)據(jù)存儲器(如map),然后來實現(xiàn)我們所謂的session數(shù)據(jù)存儲呢。既然這樣,在一些特定的場景(如分布式環(huán)境),是否可以按照這種設計思路設計另外的session存儲呢,這也是可以的。
?
接下來,我們可測試一下這種思路,是否正確。有兩個很簡單的servlet,一個為寫cookie,另一個為讀cookie。如下所示:
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 | //writeServlet //add memory cookie ????????Cookie cookie = new Cookie("memoryCookie", "12345678"); ????????cookie.setMaxAge(-1); ????????resp.addCookie(cookie); ????????//add normal cookie ????????cookie = new Cookie("persistentCookie", "abcdefg"); ????????cookie.setMaxAge(300);//one minute ????????resp.addCookie(cookie); //readServlet Cookie[] cookies = req.getCookies(); ????????for(Cookie cookie : cookies) { ????????????System.out.println( ????????????????????cookie.getPath() + "->" + cookie.getName() + "->" + cookie.getValue() + "->" + cookie.getMaxAge()); ????????} |
1??? 未訪問write,直接訪問read時
開啟F12,查看瀏覽器端的請求信息,如下所示:
只上傳了一個jsession信息(這里是因為我修改了sessionName的原因)。
而在后臺,打印結果如下所示:
| 1 | null->tomcat7utf8_session->F5B543F5D5FD4A9B78CA18D96D4CE995->-1 |
即只有jsessionId信息。
2??? 訪問write,再訪問read
開啟F12,我們查看一下訪問write之后 的cookie情況,如下所示:
以上圖為響應頭信息。
可以看出,在響應返回時,服務器返回了2個cookie,而key為memoryCookie的信息并沒有過期信息.
那我們再訪問一下write,相應信息如下所示.
這是請求頭信息:
而相應的cookie信息也同樣如下所示:
在后臺,打印的cookie信息如下所示:
| 1 2 3 | null->tomcat7utf8_session->F5B543F5D5FD4A9B78CA18D96D4CE995->-1 null->memoryCookie->12345678->-1 null->persistentCookie->abcdefg->-1 |
這里顯示的maxAge是-1,這是因為客戶端本身就沒傳遞相應的maxAge,所以未獲取到。并且這個信息從獲取來說,并沒有實際性的意義。
3 關閉瀏覽器,再訪問read
我們關閉一次瀏覽器,再看一下相應的數(shù)據(jù)信息,如下所示:
后臺打印信息如下:
null->persistentCookie->abcdefg->-1
null->tomcat7utf8_session->6B6E27A4F6B71853CC2D2C58BEE83238->-1
即可以看出,在重新打開瀏覽器(并且之前寫的persistentCookie并沒有過期)時,在請求后臺讀取時,只會發(fā)送有效的信息。而之前的內存cookie已隨著瀏覽器關閉消失了,所以這里才只會有2個信息。
需要注意的,這里的關閉瀏覽器,是把所有的標簽界面均關閉。在IE中,標簽而中是共享Cookie的,所以只關閉一個標簽是沒有作用的。
4 如何創(chuàng)建的Session
這里,我們來查看一下在后臺是如何創(chuàng)建session,并同時產(chǎn)生相應的cookie信息的。我們可以這樣認為,當我們請求后臺session時,如果沒有相應的cookie信息,后臺會產(chǎn)生一個相應的cookie,并發(fā)到客戶端(即調用response.addCookie方法)。來看一下后臺的實現(xiàn)是否如我們所說呢(這里以tomcat實現(xiàn)為參考),相應的代碼在類Request.doGetSession中,如下所示:
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | ????protected Session doGetSession(boolean create) { 。。。。。。 //這里嘗試獲取session或者創(chuàng)建一個新的session ????????// Attempt to reuse session id if one was submitted in a cookie ????????// Do not reuse the session id if it is from a URL, to prevent possible ????????// phishing attacks ????????if (connector.getEmptySessionPath() ????????????????&& isRequestedSessionIdFromCookie()) { //這里如果客戶端顯示傳遞了一個sessionId,這里直接從session池中獲取,如果獲取失敗則直接返回null,被認為是客戶端數(shù)據(jù)有問題或者是其它攻擊 ????????????session = manager.createSession(getRequestedSessionId()); ????????} else { ????????????session = manager.createSession(null); ????????} ????????//這里就是創(chuàng)建一個新的cookie,并放置在response頭中 ????????// Creating a new session cookie based on that session ????????if ((session != null) && (getContext() != null) ???????????????&& getContext().getCookies()) { ????????????String scName = context.getSessionCookieName(); ????????????if (scName == null) { ????????????????scName = Globals.SESSION_COOKIE_NAME; ????????????} //name即jsessionId或配置的sessionName value即我們所說的sessionId ????????????Cookie cookie = new Cookie(scName, session.getIdInternal()); ????????????configureSessionCookie(cookie); ????????????response.addSessionCookieInternal(cookie, context.getUseHttpOnly()); ????????} 。。。。。。 ????} |
可以看出,這和我們的大致思路是一樣的。
5 Cookie中的HttpOnly
The HttpOnly attribute is supported by most modern browsers.[19][20] On a supported browser, an HttpOnly session cookie will be used only when transmitting HTTP (or HTTPS) requests, thus restricting access from other, non-HTTP APIs (such as JavaScript). This restriction mitigates but does not eliminate the threat of session cookie theft via cross-site scripting (XSS).[21] This feature applies only to session-management cookies, and not other browser cookies.
現(xiàn)在的瀏覽器已經(jīng)支持在cookie中增加一個新的httpOnly選項,這個選項就表示這個cookie只用于在瀏覽器請求中使用,而不能被其它方式讀取和設置。比如,httpOnly式的cookie就不能被js讀取到(而常規(guī)的cookie是可以讀取的)。
在最新的J2EE6.0即Servlet3.0中,已經(jīng)支持直接在Cookie上設置httpOnly選項了。而在之間的版本,如tomcat,則可以在context.xml中設置是否支持httpOnly選項。針對像session Cookie這種會話式cookie,建議是使用httpOnly的,并且默認也是直接使用此標記的。
轉載請標明出處:i flym
本文地址:http://www.iflym.com/index.php/code/201402170002.html
轉載于:https://www.cnblogs.com/Vae1990Silence/p/4630392.html
總結
以上是生活随笔為你收集整理的会话Cookie及session的关系(Cookie Session)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 火炬之光2法师加点
- 下一篇: ELF Format 笔记(七)—— 符