1. 程式人生 > >Cookie 和Session 的區別

Cookie 和Session 的區別

cto 字符串 follow jsp技術 基礎 出現 有著 腳本 erb

作者:郭無心
鏈接:https://www.zhihu.com/question/19786827/answer/66706108
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請註明出處。 這篇是轉載的 覺得講的很好
COOKIE和SESSION有什麽區別?
cookie保存在客戶端,session保存在服務器端,
cookie目的可以跟蹤會話,也可以保存用戶喜好或者保存用戶名密碼
session用來跟蹤會話

【保存用戶的偏好設置 和 用戶密碼】
當我們登錄網站勾選保存用戶名和密碼的時候,一般保存的都是cookie,將用戶名和密碼的cookie保存到硬盤中,這樣再次登錄的時候瀏覽器直接將cookie發送到服務端驗證
,直接username和password保存到客戶端,當然這樣不安全,瀏覽器也可以加密解密這樣做,每個瀏覽器都可以有自己的加密解密方式,這樣方便了用戶,再比如用戶喜歡的網頁背景色,比如QQ空間的背景,這些信息也是可以通過cookie保存到客戶端的,這樣登錄之後直接瀏覽器直接就可以拿到相應的偏好設置。

②跟蹤會話,比如某些網站中網頁有不同的訪問權限,有只能登錄的用戶訪問的網頁或者用戶級別不同不能訪問的,但是http請求是無狀態的,每次訪問服務端是不知道是否是登錄用戶,很自然的想到在http請求報文中加入登錄標識就可以了,這個登錄標識就可以是cookie,這樣的cookie服務端要保存有所有登錄用戶的cookie,這樣請求報文來了之後拿到登錄標識cookie,在服務端進行比較久可以了。再比如購物網站,多次點擊添加商品到購物車客戶端很容易知道哪些物品在購物車中,但是服務端怎麽知道每次添加的物品放到哪個登錄用戶的購物車中呢?也需要請求報文中帶著cookie才行
(在不登陸的情況下京東也是可以不斷添加商品的,推測應該是登錄的時候一並創建cookie並且發送物品信息),這些cookie都是為了跟蹤會話用的,所以客戶端有,服務端也有,並且服務端有全部的會話cookie。

後面衍生出session技術,session技術是要使用到cookie的,之所以出現session技術,主要是為了安全。

http是無狀態的協議,客戶每次讀取web頁面時,服務器都打開新的會話,而且服務器也不會自動維護客戶的上下文信息,那麽要怎麽才能實現網上商店中的購物車呢,session就是一種保存上下文信息的機制,它是針對每一個用戶的,變量的值保存在服務器端,通過SessionID來區分不同的客戶,session是以cookie或URL重寫為基礎的,默認使用cookie來實現

,系統會創造一個名為JSESSIONID的輸出cookie,我們叫做session cookie,以區別persistent cookies,也就是我們通常所說的cookie,註意session cookie是存儲於瀏覽器內存中的,並不是寫到硬盤上的,這也就是我們剛才看到的JSESSIONID,我們通常情是看不到JSESSIONID的,但是當我們把瀏覽器的cookie禁止後,web服務器會采用URL重寫的方式傳遞Sessionid,我們就可以在地址欄看到 sessionid=KWJHUG6JJM65HS2K6之類的字符串。

技術分享大家請看在HTTP請求報文頭的最後一行有cookie,不過是JSessionID的cookie值


Cookie: $Version=1; Skin=new;jsessionid=5F4771183629C9834F8382E23BE13C4C

比如前兩個值,應該屬於偏好設置之類的。


服務端是怎麽知道客戶端的多個請求是隸屬於一個Session呢?註意到後臺的那個jsessionid=5F4771183629C9834F8382E23BE13C4C木有?原來就是通過HTTP請求報文頭的Cookie屬性的jsessionid的值關聯起來的!(當然也可以通過重寫URL的方式將會話ID附帶在每個URL的後面哦)
明白了原理,我們就可以很容易的分辨出persistent cookies和session cookie的區別了,網上那些關於兩者安全性的討論也就一目了然了,session cookie針對某一次會話而言,會話結束session cookie也就隨著消失了,而persistent cookie只是存在於客戶端硬盤上的一段文本(通常是加密的),而且可能會遭到cookie欺騙以及針對cookie的跨站腳本攻擊,自然不如 session cookie安全了。


通常session cookie是不能跨窗口使用的,當你新開了一個瀏覽器窗口進入相同頁面時,系統會賦予你一個新的sessionid,這樣我們信息共享的目的就達不到了,此時我們可以先把sessionid保存在persistent cookie中,然後在新窗口中讀出來,就可以得到上一個窗口SessionID了,這樣通過session cookie和persistent cookie的結合我們就實現了跨窗口的session tracking(會話跟蹤)
在一些web開發的書中,往往只是簡單的把Session和cookie作為兩種並列的http傳送信息的方式,session cookies位於服務器端,persistent cookie位於客戶端,可是session又是以cookie為基礎的,明白的兩者之間的聯系和區別,我們就不難選擇合適的技術來開發web service了。


部分參考自:session與cookie的區別

===================分割線==============
舉個QQ空間的例子:
① 當我們登錄QQ空間的時候,可以選擇保存用戶名和密碼,這樣下次登錄的時候瀏覽器可以自動填充或者自動登陸,此時使用的是cookie技術,將於
http://qzone.qq.com/
域名對應的cookie保存到硬盤中,下次訪問的時候瀏覽器查找保存在硬盤中的與該域名對應的cookie填充。

②登錄之後,我們可能做些操作,比如刪除日誌,發表說說,這些只有登錄用戶才能做的事情可以使用cookie也可以使用session進行會話跟蹤

③空間的喜好設置可以保存到硬盤cookie當中。

-------------------------------------------------------------------------------------------------------------------------
其實說白了session就是用來保存會話的cookie。
下面介紹下Java中Servlet的session管理
http://lavasoft.blog.51cto.com/62575/275589  深入理解HTTP Session

session在web開發中是一個非常重要的概念,這個概念很抽象,很難定義,也是最讓人迷惑的一個名詞,也是最多被濫用的名字之一,在不同的場合,session一次的含義也很不相同。這裏只探討HTTP Session。

為了說明問題,這裏基於Java Servlet理解Session的概念與原理,這裏所說Servlet已經涵蓋了JSP技術,因為JSP最終也會被編譯為Servlet,兩者有著相同的本質。

在Java中,HTTP的Session對象用javax.servlet.http.HttpSession來表示。

1、概念:Session代表服務器與瀏覽器的一次會話過程,這個過程是連續的,也可以時斷時續的。在Servlet中,session指的是HttpSession類的對象,這個概念到此結束了,也許會很模糊,但只有看完本文,才能真正有個深刻理解。

2、Session創建的時間是:
一個常見的誤解是以為session在有客戶端訪問時就被創建,然而事實是直到某server端程序調用 HttpServletRequest.getSession(true)這樣的語句時才被創建,註意如果JSP沒有顯示的使用 <% @page session="false"%> 關閉session,則JSP文件在編譯成Servlet時將會自動加上這樣一條語句 HttpSession session = HttpServletRequest.getSession(true);這也是JSP中隱含的 session對象的來歷。
由於session會消耗內存資源,因此,如果不打算使用session,應該在所有的JSP中關閉它。

引申:
1)、訪問*.html的靜態資源因為不會被編譯為Servlet,也就不涉及session的問題。
2)、當JSP頁面沒有顯式禁止session的時候,在打開瀏覽器第一次請求該jsp的時候,服務器會自動為其創建一個session,並賦予其一個sessionID,發送給客戶端的瀏覽器。以後客戶端接著請求本應用中其他資源的時候,會自動在請求頭上添加:
Cookie:JSESSIONID=客戶端第一次拿到的session ID
這樣,服務器端在接到請求時候,就會收到session ID,並根據ID在內存中找到之前創建的session對象,提供給請求使用。這也是session使用的基本原理----搞不懂這個,就永遠不明白session的原理。
下面是兩次請求同一個jsp,請求頭信息: 備註:【圖的信息應該是包含 Cookie:JSESSIONID=客戶端第一次拿到的session ID 這樣的信息在http請求頭的一個截圖 】
通過圖可以清晰發現,第二次請求的時候,已經添加session ID的信息。
3、Session刪除的時間是:
1)Session超時:超時指的是連續一定時間服務器沒有收到該Session所對應客戶端的請求,並且這個時間超過了服務器設置的Session超時的最大時間。
2)程序調用HttpSession.invalidate()
3)服務器關閉或服務停止

4、session存放在哪裏:服務器端的內存中。不過session可以通過特殊的方式做持久化管理。

5、session的id是從哪裏來的,sessionID是如何使用的:當客戶端第一次請求session對象時候,服務器會為客戶端創建一個session,並將通過特殊算法算出一個session的ID,用來標識該session對象,當瀏覽器下次(session繼續有效時)請求別的資源的時候,瀏覽器會偷偷地將sessionID放置到請求頭中,服務器接收到請求後就得到該請求的sessionID,服務器找到該id的session返還給請求者(Servlet)使用。一個會話只能有一個session對象,對session來說是只認id不認人。

6、session會因為瀏覽器的關閉而刪除嗎?
不會,session只會通過上面提到的方式去關閉。

7、同一客戶端機器多次請求同一個資源,session一樣嗎?
一般來說,每次請求都會新創建一個session。


其實,這個也不一定的,總結下:對於多標簽的瀏覽器(比如360瀏覽器)來說,在一個瀏覽器窗口中,多個標簽同時訪問一個頁面,session是一個。對於多個瀏覽器窗口之間,同時或者相隔很短時間訪問一個頁面,session是多個的,和瀏覽器的進程有關。對於一個同一個瀏覽器窗口,直接錄入url訪問同一應用的不同資源,session是一樣的。

8、session是一個容器,可以存放會話過程中的任何對象。

9、session因為請求(request對象)而產生,同一個會話中多個request共享了一session對象,可以直接從請求中獲取到session對象。

10、其實,session的創建和使用總在服務端,而瀏覽器從來都沒得到過session對象。但瀏覽器可以請求Servlet(jsp也是Servlet)來獲取session的信息。客戶端瀏覽器真正緊緊拿到的是session ID,而這個對於瀏覽器操作的人來說,是不可見的,並且用戶也無需關心自己處於哪個會話過程中。
---------------------------------------------------------------------------------------------------
比如下面一段使用session的代碼
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{

   response.setContentType("text/html");
   response.setCharacterEncoding("utf-8");
   PrintWriter out = response.getWriter();
   // 得到用戶名和密碼,驗證
   String u = request.getParameter("username");
   String p = request.getParameter("password");

   UserBeanBO ubb = new UserBeanBO();
   if (ubb.checkUser(u, p))
   {
	// 1.把成功登陸的用戶所有信息放入session
	UserBean ub = ubb.getUserBean(u);
	request.getSession().setAttribute("userInfo", ub);
	// 2.把購物車的信息取出
	MyCartBO mcb = (MyCartBO)request.getSession().getAttribute("mycart");    
	ArrayList al = mcb.showMyCart();
	// 把al放入request
	request.setAttribute("mycartInfo", al);
	// 用戶合法
	request.getRequestDispatcher("success.jsp").forward(request,response);
  } else
  {
    // 用戶不合法
      request.getRequestDispatcher("error.jsp").forward(request, response);		  	
  }

}

HttpSession  javax.servlet.http.HttpServletRequest.getSession()

Returns the current session associated with this request, or if the request 
does not have a session, creates one.

Returns: the HttpSession associated with this request

See Also:

getSession(boolean)
javax.servlet.http.HttpServletRequest.getSession() 將會返回當前request相關聯的HttpSession對象,如果不存在,將會創建一個。

翻譯一下,當一個瀏覽器請求來到之後,Servlet處理程序(Servlet容器內部實現)將會主動檢查請求信息Cookie當中是否有JSESSIONID,若有,找到對應JSESSION的HttpSession對象,如果沒有,創建一個,具體的機制在Servlet容器的實現當中。

Cookie 和Session 的區別