1. 程式人生 > >session and cookie

session and cookie

esp true servle tex fire 購物車 之前 tps key

會話(Session)跟蹤是Web程序中常用的技術,用來跟蹤用戶的整個會話。常用的會話跟蹤技術是Cookie與Session。Cookie通過在客戶端記錄信息確定用戶身份Session通過在服務器端記錄信息確定用戶身份

本章將系統地講述Cookie與Session機制,並比較說明什麽時候不能用Cookie,什麽時候不能用Session。

1.1 Cookie機制

在程序中,會話跟蹤是很重要的事情。理論上,一個用戶的所有請求操作都應該屬於同一個會話,而另一個用戶的所有請求操作則應該屬於另一個會話,二者不能混淆。例如,用戶A在超市購買的任何商品都應該放在A的購物車內,不論是用戶A什麽時間購買的,這都是屬於同一個會話的,不能放入用戶B或用戶C的購物車內,這不屬於同一個會話。

而Web應用程序是使用HTTP協議傳輸數據的。HTTP協議是無狀態的協議。一旦數據交換完畢,客戶端與服務器端的連接就會關閉,再次交換數據需要建立新的連接。這就意味著服務器無法從連接上跟蹤會話。即用戶A購買了一件商品放入購物車內,當再次購買商品時服務器已經無法判斷該購買行為是屬於用戶A的會話還是用戶B的會話了。要跟蹤該會話,必須引入一種機制。

Cookie就是這樣的一種機制。它可以彌補HTTP協議無狀態的不足。在Session出現之前,基本上所有的網站都采用Cookie來跟蹤會話。

1.1.1 什麽是Cookie

Cookie意為“甜餅”,是由W3C組織提出,最早由Netscape社區發展的一種機制。目前Cookie已經成為標準,所有的主流瀏覽器如IE、Netscape、Firefox、Opera等都支持Cookie。

由於HTTP是一種無狀態的協議,服務器單從網絡連接上無從知道客戶身份。怎麽辦呢?就給客戶端們頒發一個通行證吧,每人一個,無論誰訪問都必須攜帶自己通行證。這樣服務器就能從通行證上確認客戶身份了。這就是Cookie的工作原理

Cookie實際上是一小段的文本信息。客戶端請求服務器,如果服務器需要記錄該用戶狀態,就使用response向客 戶端瀏覽器頒發一個Cookie。客戶端瀏覽器會把Cookie保存起來。當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務 器。服務器檢查該Cookie,以此來辨認用戶狀態。服務器還可以根據需要修改Cookie的內容。

技術分享圖片

查看某個網站頒發的Cookie很簡單。在瀏覽器地址欄輸入javascript:alert (document. cookie)就可以了(需要有網才能查看)。JavaScript腳本會彈出一個對話框顯示本網站頒發的所有Cookie的內容,如圖1.1所示。

技術分享圖片

圖1.1 Baidu網站頒發的Cookie

圖1.1中彈出的對話框中顯示的為Baidu網站的Cookie。其中第一行BAIDUID記錄的就是筆者的身份helloweenvsfei,只是Baidu使用特殊的方法將Cookie信息加密了。

除了使用Cookie,Web應用程序中還經常使用Session來記錄客戶端狀態。Session是服務器端使用的一種記錄客戶端狀態的機制,使用上比Cookie簡單一些,相應的也增加了服務器的存儲壓力

1.2.1 什麽是Session

Session是另一種記錄客戶狀態的機制,不同的是Cookie保存在客戶端瀏覽器中,而Session保存在服務器上。客戶端瀏覽器訪問服務器的時候,服務器把客戶端信息以某種形式記錄在服務器上。這就是Session。客戶端瀏覽器再次訪問時只需要從該Session中查找該客戶的狀態就可以了。

如果說Cookie機制是通過檢查客戶身上的“通行證”來確定客戶身份的話,那麽Session機制就是通過檢查服務器上的“客戶明細表”來確認客戶身份。Session相當於程序在服務器上建立的一份客戶檔案,客戶來訪的時候只需要查詢客戶檔案表就可以了。

1.2.2 實現用戶登錄

Session對應的類為javax.servlet.http.HttpSession類。每個來訪者對應一個Session對象,所有該客戶的狀態信息都保存在這個Session對象裏。Session對象是在客戶端第一次請求服務器的時候創建的。 Session也是一種key-value的屬性對,通過getAttribute(Stringkey)和setAttribute(String key,Objectvalue)方法讀寫客戶狀態信息。Servlet裏通過request.getSession()方法獲取該客戶的 Session,

例如:

HttpSession session = request.getSession(); // 獲取Session對象

session.setAttribute("loginTime", new Date()); // 設置Session中的屬性

out.println("登錄時間為:" +(Date)session.getAttribute("loginTime")); // 獲取Session屬性

request還可以使用getSession(boolean create)來獲取Session。區別是如果該客戶的Session不存在,request.getSession()方法會返回null,而 getSession(true)會先創建Session再將Session返回。

Servlet中必須使用request來編程式獲取HttpSession對象,而JSP中內置了Session隱藏 對象,可以直接使用。如果使用聲明了<%@page session="false" %>,則Session隱藏對象不可用。下面的例子使用Session記錄客戶賬號信息。

源代碼如下:

代碼1.9 session.jsp

<%@ page language="java" pageEncoding="UTF-8"%>

<jsp:directive.page import="com.helloweenvsfei.sessionWeb.bean.Person"/>

<jsp:directive.page import="java.text.SimpleDateFormat"/>

<jsp:directive.page import="java.text.DateFormat"/>

<jsp:directive.page import="java.util.Date"/>

<%!

DateFormat dateFormat = newSimpleDateFormat("yyyy-MM-dd"); // 日期格式化器

%>

<%

response.setCharacterEncoding("UTF-8"); // 設置request編碼

Person[] persons =

{

// 基礎數據,保存三個人的信息

new Person("Liu Jinghua","password1", 34, dateFormat.parse
("1982-01-01")),

new Person("Hello Kitty","hellokitty", 23, dateFormat.parse
("1984-02-21")),

new Person("Garfield", "garfield_pass",23, dateFormat.parse
("1994-09-12")),

};

String message = ""; // 要顯示的消息

if(request.getMethod().equals("POST"))

{

// 如果是POST登錄

for(Person person :persons)

{

// 遍歷基礎數據,驗證賬號、密碼

// 如果用戶名正確且密碼正確

if(person.getName().equalsIgnoreCase(request.getParameter("username"))&&person.getPassword().equals(request.getParameter("password")))

{

// 登錄成功,設置將用戶的信息以及登錄時間保存到Session

session.setAttribute("person", person); // 保存登錄的Person

session.setAttribute("loginTime", new Date()); // 保存登錄的時間

response.sendRedirect(request.getContextPath() + "/welcome.jsp");

return;

}

}

message = "用戶名密碼不匹配,登錄失敗。"; // 登錄失敗

}

%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01Transitional//EN">

<html>

// ... HTML代碼為一個FORM表單,代碼略,請看隨書光盤

</html>

登錄界面驗證用戶登錄信息,如果登錄正確,就把用戶信息以及登錄時間保存進Session,然後轉到歡迎頁面welcome.jsp。welcome.jsp中從Session中獲取信息,並將用戶資料顯示出來。

welcome.jsp代碼如下:

代碼1.10 welcome.jsp

<%@ page language="java" pageEncoding="UTF-8"%>

<jsp:directive.pageimport="com.helloweenvsfei.sessionWeb.bean.Person"/>

<jsp:directive.page import="java.text.SimpleDateFormat"/>

<jsp:directive.page import="java.text.DateFormat"/>

<jsp:directive.page import="java.util.Date"/>

<%!

DateFormat dateFormat = newSimpleDateFormat("yyyy-MM-dd"); // 日期格式化器

%>

<%

Person person =(Person)session.getAttribute("person"); // 獲取登錄的person

Date loginTime =(Date)session.getAttribute("loginTime"); // 獲取登錄時間

%>

// ... 部分HTML代碼略

<table>

<tr><td>您的姓名:</td>

<td><%= person.getName()%></td>

</tr>

<tr><td>登錄時間:</td>

<td><%= loginTime%></td>

</tr>

<tr><td>您的年齡:</td>

<td><%= person.getAge()%></td>

</tr>

<tr><td>您的生日:</td>

<td><%=dateFormat.format(person.getBirthday()) %></td>

</tr>

</table>

程序運行效果如圖1.8所示。

技術分享圖片

圖1.8 使用Session記錄用戶信息

註意程序中Session中直接保存了Person類對象與Date類對象,使用起來要比Cookie方便。

當多個客戶端執行程序時,服務器會保存多個客戶端的Session。獲取Session的時候也不需要聲明獲取誰的Session。Session機制決定了當前客戶只會獲取到自己的Session,而不會獲取到別人的Session。各客戶的Session也彼此獨立,互不可見

註意:Cookie功能需要瀏覽器的支持。

如果瀏覽器不支持Cookie(如大部分手機中的瀏覽器)或者把Cookie禁用了,Cookie功能就會失效。

不同的瀏覽器采用不同的方式保存Cookie。

IE瀏覽器會在“C:\Documents and Settings\你的用戶名\Cookies”文件夾下以文本文件形式保存,一個文本文件保存一個Cookie。

session and cookie