HTTP Session
一、浅析
HTTP协议(http://www.w3.org/Protocols/)是“一次性单向”协议。
服务端不能主动连接客户端,只能被动等待并答复客户端请求。客户端连接服务端,发出一个HTTP Request,服务端处理请求,并且返回一个HTTP Response给客户端,本次HTTP Request-Response Cycle结束。
我们看到,HTTP协议本身并不能支持服务端保存客户端的状态信息。于是,Web Server中引入了session的概念,用来保存客户端的状态信息。
这里用一个形象的比喻来解释session的工作方式。假设Web Server是一个商场的存包处,HTTP Request是一个顾客,第一次来到存包处,管理员把顾客的物品存放在某一个柜子里面(这个柜子就相当于Session),然后把一个号码牌交给这个顾客,作为取包凭证(这个号码牌就是Session ID)。顾客(HTTP Request)下一次来的时候,就要把号码牌(Session ID)交给存包处(Web Server)的管理员。管理员根据号码牌(Session ID)找到相应的柜子(Session),根据顾客(HTTP Request)的请求,Web Server可以取出、更换、添加柜子(Session)中的物品,Web Server也可以让顾客(HTTP Request)的号码牌和号码牌对应的柜子(Session)失效。顾客(HTTP Request)的忘性很大,管理员在顾客回去的时候(HTTP Response)都要重新提醒顾客记住自己的号码牌(Session ID)。这样,顾客(HTTP Request)下次来的时候,就又带着号码牌回来了。
Session ID实际上是在客户端和服务端之间通过HTTP Request和HTTP Response传来传去的。号码牌(Session ID)必须包含在HTTP Request里面。关于HTTP Request的具体格式,请参见HTTP协议(http://www.w3.org/Protocols/)。这里只做一个简单的介绍。
在Java Web Server(即Servlet/JSP Server)中,Session ID用jsessionid表示(请参见Servlet规范)。
HTTP Request一般由3部分组成:
(1)Request Line
这一行由HTTP Method(如GET或POST)、URL、和HTTP版本号组成。
例如,GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1
GET http://www.google.com/search?q=Tomcat HTTP/1.1
POST http://www.google.com/search HTTP/1.1
GET http://www.somsite.com/menu.do;jsessionid=1001 HTTP/1.1
(2)Request Headers
这部分定义了一些重要的头部信息,如,浏览器的种类,语言,类型。Request Headers中还可以包括Cookie的定义。例如:
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)
Accept-Language: en-us
Cookie: jsessionid=1001
(3)Message Body
如果HTTP Method是GET,那么Message Body为空。
如果HTTP Method是POST,说明这个HTTP Request是submit一个HTML Form的结果,
那么Message Body为HTML Form里面定义的Input属性。例如,
user=guest
password=guest
jsessionid=1001
主意,如果把HTML Form元素的Method属性改为GET。那么,Message Body为空,所有的Input属性都会加在URL的后面。你在浏览器的URL地址栏中会看到这些属性,类似于
http://www.somesite/login.do?user=guest&password=guest&jsessionid=1001
从理论上来说,这3个部分(Request URL,Cookie Header, Message Body)都可以用来存放Session ID。由于Message Body方法必须需要一个包含Session ID的HTML Form,所以这种方法不通用。
一般用来实现Session的方法有两种:
(1)URL重写。
Web Server在返回Response的时候,检查页面中所有的URL,包括所有的连接,和HTML Form的Action属性,在这些URL后面加上“;jsessionid=XXX”。
下一次,用户访问这个页面中的URL。jsessionid就会传回到Web Server。
(2)Cookie。
如果客户端支持Cookie,Web Server在返回Response的时候,在Response的Header部分,加入一个“set-cookie: jsessionid=XXXX”header属性,把jsessionid放在Cookie里传到客户端。
客户端会把Cookie存放在本地文件里,下一次访问Web Server的时候,再把Cookie的信息放到HTTP Request的“Cookie”header属性里面,这样jsessionid就随着HTTP Request返回给Web Server。
二、相关资料
前面是我自作聪明的一段个人浅见,下面我来找点权威资料支持。
http://www.w3.org/Protocols/
Use of HTTP State Management (RFC 2964).
ftp://ftp.rfc-editor.org/in-notes/rfc2964.txt
这个文件是定义“HTTP State Management”扩展协议部分。里面有这么一段,
It's important to realize that similar capabilities may also be achieved using the "bare" HTTP protocol, and/or dynamically-generated
HTML, without the State Management extensions. For example, state information can be transmitted from the service to the user by embedding a session identifier in one or more URLs which appear in HTTP redirects, or dynamically generated HTML; and the state information may be returned from the user to the service when such URLs appear in a GET or POST request. HTML forms can also be used to pass state information from the service to the user and back, without the user being aware of this happening.
这段话的意思是说,不用这个 “HTTP State Management”扩展协议部分,我们也可以用“纯粹”的HTTP协议实现Session -- 比如URL重写,HTML Form等。
这里面没有提到Cookie。因为“HTTP State Management” 扩展协议部分本身包括了关于Cookie的内容。这一点可以通过
HTTP State Management Mechanism (RFC 2965),
ftp://ftp.rfc-editor.org/in-notes/rfc2965.txt
看出来。
STATE AND SESSIONS
This document describes a way to create stateful sessions with HTTP requests and responses. Currently, HTTP servers respond to each client request without relating that request to previous or subsequent requests; the state management mechanism allows clients and servers that wish to exchange state information to place HTTP requests and responses within a larger context, which we term a "session". This context might be used to create, for example, a "shopping cart", in which user selections can be aggregated before purchase, or a magazine browsing system, in which a user's previous reading affects which offerings are presented.
Neither clients nor servers are required to support cookies. A server MAY refuse to provide content to a client that does not return the cookies it sends.
后面还给出了例子(其中的汉语部分是我加的)。
4.1 Example 1
Most detail of request and response headers has been omitted. Assume
the user agent has no stored cookies.
1. User Agent -> Server
POST /acme/login HTTP/1.1
[form data]
User identifies self via a form.
2. Server -> User Agent
HTTP/1.1 200 OK
Set-Cookie2: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"
Cookie reflects user's identity.
(这里面的 Customer="WILE_E_COYOTE" 应该就是从Form Data里面来的,这时候又传回给了客户端)
3. User Agent -> Server
POST /acme/pickitem HTTP/1.1
Cookie: $Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"
[form data]
User selects an item for "shopping basket".
4. Server -> User Agent
HTTP/1.1 200 OK
Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1";
Path="/acme"
Shopping basket contains an item.
(这个火箭发射器显然也是从Form Data来的。但为什么Part_Number="Rocket_Launcher_0001"也需要传回给客户端?
Customer="WILE_E_COYOTE"; 应该是在传统的”Set-Cookie”里面传回给客户端的。” Set-Cookie2” 的作用应该是向Cookie里面添加东西。)
5. User Agent -> Server
POST /acme/shipping HTTP/1.1
Cookie: $Version="1";
Customer="WILE_E_COYOTE"; $Path="/acme";
Part_Number="Rocket_Launcher_0001"; $Path="/acme"
[form data]
User selects shipping method from form.
(客户传给服务器的Cookie里面包括了Customer和Part_Number)
6. Server -> User Agent
HTTP/1.1 200 OK
Set-Cookie2: Shipping="FedEx"; Version="1"; Path="/acme"
New cookie reflects shipping method.
7. User Agent -> Server
POST /acme/process HTTP/1.1
Cookie: $Version="1";
Customer="WILE_E_COYOTE"; $Path="/acme";
Part_Number="Rocket_Launcher_0001"; $Path="/acme";
Shipping="FedEx"; $Path="/acme"
[form data]
User chooses to process order.
8. Server -> User Agent
HTTP/1.1 200 OK
Transaction is complete.
The user agent makes a series of requests on the origin server, after each of which it receives a new cookie. All the cookies have the same Path attribute and (default) domain. Because the request-URIs all path-match /acme, the Path attribute of each cookie, each request contains all the cookies received so far.
(看到这里,我才大致明白,原来那个$Path="/acme" 大致起着 JSessionID的作用)
三、Tomcat5的HTTP Session实现
下面我们来看Tomcat5的源代码如何支持HTTP 1.1 Session。
我们可以用jsessionid, Set-Cookie等关键字搜索Tomcat5源代码。
首先,我们来看常量定义:
org.apache.catalina.Globals
/**
* The name of the cookie used to pass the session identifier back
* and forth with the client.
*/
public static final String SESSION_COOKIE_NAME = "JSESSIONID";
/**
* The name of the path parameter used to pass the session identifier
* back and forth with the client.
*/
public static final String SESSION_PARAMETER_NAME = "jsessionid";
Cookie里面用大写的JSESSIONID,URL后缀用的是小写的jsessionid。
Session的具体实现类是org.apache.catalina.session.StandardSession。一个Tomcat Server的所有Session都由一个Manager(拥有一个Context)统一管理。我估计有一个 Session Listener 专门管理Cluster之间的Session数据复制,具体的我没有追查下去。
另外几个重要的相关类是org.apache.coyote.tomcat5包下面的CoyoteRequest , CoyoteResponse, CoyoteAdapter三个类。
org.apache.coyote.tomcat5.CoyoteResponse类的toEncoded()方法支持URL重写。
String toEncoded(String url, String sessionId) {
…
StringBuffer sb = new StringBuffer(path);
if( sb.length() > 0 ) { // jsessionid can't be first.
sb.append(";jsessionid=");
sb.append(sessionId);
}
sb.append(anchor);
sb.append(query);
return (sb.toString());
}
我们来看org.apache.coyote.tomcat5.CoyoteRequest的两个方法configureSessionCookie()
doGetSession()用Cookie支持jsessionid.
/**
* Configures the given JSESSIONID cookie.
*
* @param cookie The JSESSIONID cookie to be configured
*/
protected void configureSessionCookie(Cookie cookie) {
…
}
HttpSession doGetSession(boolean create){
…
// Creating a new session cookie based on that session
if ((session != null) && (getContext() != null)
&& getContext().getCookies()) {
Cookie cookie = new Cookie(Globals.SESSION_COOKIE_NAME,
session.getId());
margin-top: 0in; margin-right: 0in; margin-bottom: 0pt
分享到:
相关推荐
### Session与Cookie的区别和联系 ...通过以上分析可以看出,Session和Cookie在Web开发中扮演着重要的角色,它们各有优缺点,适用于不同的场景。理解它们的区别和联系对于设计高效且安全的Web应用至关重要。
在分析提供的标签“源码”和“工具”时,我们可以推断这篇博文可能深入讲解了ThinkPHP5框架内部关于Session和Cookie的实现原理,以及如何利用这些工具进行实际开发。作者可能还分享了一些调试技巧或最佳实践,帮助...
在“源码”和“工具”标签的提示下,我们可以推断文章可能涉及了Cookie和Session的实现细节,或许还涵盖了如何在实际项目中使用它们,或者分析了一些常见的库和框架如何处理Session和Cookie。例如,Spring框架提供了...
### Cookie机制与Session机制的区别及关系 在现代网络应用中,服务器端与客户端之间的状态保持是至关重要的,尤其是在无状态的HTTP协议下。Cookie机制与Session机制是两种常用的状态管理方式,它们各自拥有独特的...
5. **使用场景**:Cookie常用于记录用户状态(如登录信息),实现个性化功能(如记住首选项)和跟踪用户行为(如网站统计分析)。 在实际应用中,开发者通常结合Session和Cookie来实现更复杂的用户会话管理。比如,...
### Cookie机制和Session机制 #### 一、基本概念与背景 在现代Web应用中,为了实现用户认证、个性化设置等功能,通常需要在客户端与服务器之间维持一段时间内的状态信息。然而,HTTP协议本质上是无状态的,这意味...
主要介绍了thinkphp中session和cookie无效的解决方法,涉及针对BOM头的分析与删除方法,具有一定的参考借鉴价值,需要的朋友可以参考下
开发者不需要手动创建session,当用户访问时,SessionMiddleware会根据请求中的cookie信息(主要是session cookie)来获取或创建session对象。 **Django中Cookie的操作**: - 使用`response.set_cookie(key, value...
现在,我们来分析Cookie的局限性: 1. 数据大小限制:Cookie的最大大小为4KB,这意味着无法存储大量数据,如用户详细信息或购物车内容。 2. 安全性:由于Cookie存储在客户端,容易受到跨站脚本攻击(XSS)和跨站请求...
通过上述分析,我们可以看出Cookie和Session各有特点,在实际应用中可以根据具体需求选择合适的技术。对于简单且不涉及敏感信息的应用,使用Cookie可能更为方便;而对于需要高度安全性以及大量用户状态信息的应用,...
**标题:Cookie分析工具** **概述** Cookie分析工具是一种专门用于检查、管理和分析网页Cookie的专业软件。在本案例中提到的“IECookiesView v1.73”是一款针对Internet Explorer浏览器的Cookie查看器,它允许用户...
- 统计分析:如访问次数统计、流量来源等信息,也可以通过Cookie进行记录。 #### 四、示例代码解析 下面是一段Java示例代码,展示了如何获取和处理Cookie: ```java cookie[] cookies = request.getCookies(); ...
在ASP.NET开发中,Application、Session和Cookie对象是三个至关重要的概念,它们分别用于不同的数据存储和传递场景。下面我们将详细分析这三个对象的功能、用法以及它们在网站应用程序中的作用。 1. **Application...
### 对Session和Cookie的深刻理解 #### Session与Cookie的基本概念 在Web开发中,了解Session和Cookie是非常重要的,因为它们是实现用户会话管理和状态跟踪的关键技术。简单来说,Session和Cookie都用于存储用户...
- **跟踪用户行为**:网站可以通过分析用户的Cookie数据,了解用户的浏览习惯,提供更精准的内容或广告推荐。 #### 2. Session 的原理与优势 Session是一种服务器端的机制,用于跟踪用户的活动会话。它通过为每个...
在IT行业中,网络应用程序开发是不可或缺的一部分,而`Application`、`Session`和`Cookie`则是构建此类应用时经常会用到的关键概念。本教程将通过一个聊天室小例子,深入探讨这三个概念及其在ASP.NET中的具体应用。 ...
- **管理Session生命周期**:可以调整`session.cookie_lifetime`和`session.gc_maxlifetime`配置参数,控制Cookie和Session数据的存活时间。 在实际应用中,开发者应根据项目需求和性能考虑选择使用Cookie还是...