`
阅读更多
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());

            configureSessionCookie(cookie);

            ((HttpServletResponse) response).addCookie(cookie);

        }

      …

    }


四、More

HTTP Session的协议、规范、实现大概就是这些。

另外,在frameset中使用Session的情况有些复杂,不同环境表现可能不同。

其余相关的概念有“单点登录”(Sing Sign On – SSO), Domain, Cluster, Proxy, Cache等。
分享到:
评论
1 楼 动物园的猪 2007-01-06  
好贴,不过如何tomcat虽然回写了jsessionid,但是,ie端并没有真正产生一个cookie文件与之对应,而仅仅在内存中保存了这个id,然后new request的时候发送回来。

如何让客户端明确地生成一个cookie文件呢?

相关推荐

    理解HTTP session原理及应用

    HTTP Session 是Web开发中一种重要的技术,用于在客户端和服务器之间维持状态,尤其是在无状态的HTTP协议下。本文将深入探讨HTTP Session的原理及其在实际应用中的作用。 首先,理解"session"一词的含义至关重要。...

    spring session redis分布式session

    然而,传统的HTTP Session在分布式环境中面临着同步难题,因为每个服务器节点都维护独立的Session,导致跨服务器时Session数据不同步。为了解决这个问题,Spring Session提供了一种优雅的解决方案,特别是结合Redis...

    SpringSession+Redis实现Session共享案例

    - `SpringSession` 是Spring生态系统的一个扩展,它允许我们将HTTP Session数据存储在外部存储(如Redis)中,而不是传统的Java EE容器内。这样,Session数据可以在多台服务器之间共享,解决了负载均衡下的Session...

    spring-session实现session共享

    传统的HTTP Session机制在单服务器环境下工作良好,但当涉及到跨域、多服务器间的用户状态同步时,其局限性就显现出来。Spring-Session作为一个优秀的解决方案,它结合了Redis等分布式存储,有效地解决了这个问题,...

    birt 使用session数据, 通过servlet访问

    标题 "birt 使用session数据, 通过servlet访问" 涉及到的是在BIRT(Business Intelligence and Reporting Tools)报告引擎中如何利用HTTP Session来传递和使用数据,特别是通过Servlet进行访问。在这个场景下,...

    spring session实现分布式会话管理

    Spring Session 的核心理念是将传统的 HTTP Session 数据存储和管理从应用服务器迁移到更灵活、可扩展的数据存储层,如 Redis、MongoDB 或者 JDBC 数据库。这样可以解决在微服务、云环境或者负载均衡场景下,保持...

    JSP实验-购物车(用session实现)

    在这个实验中,我们将使用JavaServer Pages (JSP) 技术来创建一个简单的购物车,主要依赖于HTTP Session来保存用户的选择。以下是对这个实验的详细讲解。 **1. 购物车的基本概念** 购物车是电子商务网站的核心组件...

    web项目集群时共享session方案实践

    6. **基于HTTP Session Clustering** - 利用Java的`HttpSessionBindingListener`接口和`HttpSessionAttributeListener`接口监听Session事件,实现Session的同步。 - 优点:与应用服务器的集群支持紧密集成。 - ...

    使用redis管理对象缓存,可代替session

    标题中的“使用redis管理对象缓存,可代替session”指的是在Web应用中,利用Redis作为对象缓存系统来替代传统的HTTP Session。Redis是一款高性能的Key-Value存储系统,它可以用来存储临时性的数据,如用户的Session...

    tomcat 做session共享所需jar包压缩包

    首先,我们来了解下Tomcat Session共享的必要性:当一个Web应用部署在多台Tomcat服务器上,传统的HTTP Session无法跨服务器保持状态,可能导致用户登录状态丢失或数据不一致。因此,需要一种机制来在所有服务器之间...

    基于redis的集群session共享jar包

    然而,当应用部署在多台服务器上时,传统的HTTP session管理就会遇到问题,因为session是存储在单个服务器上的,这导致了数据的不共享,影响了用户体验。为了解决这个问题,我们可以利用Redis来实现基于集群的...

    springboot 项目,基于springsession整合redis实现登录拦截功能

    在这样的系统中,用户会话(Session)管理成为一个挑战,因为传统的基于HTTP Session的方法无法在多个服务之间共享数据。Spring Session应运而生,它提供了一种在分布式环境中管理Session的解决方案。本项目是基于...

    对session和cookie的一些理解

    例如,Spring框架提供了丰富的Session管理功能,包括基于HTTP Session和基于分布式存储的Session管理。 总的来说,理解并正确使用Session和Cookie对于Web开发者至关重要,它们是构建动态、交互式Web应用的基础。在...

    memcached共享session需要的jar包

    这个组件负责将HTTP session的状态存储在Memcached服务器上,从而实现在不同应用服务器之间的共享。 4. **kryo-1.04.jar 和 kryo-serializers-0.10.jar**:Kryo是一个高效的序列化库,用于将Java对象转换为字节流,...

    43_说说你们的分布式session方案是啥?怎么做的?.zip

    6. **HTTP Session Sticky Sessions**:这是一种负载均衡策略,通过负载均衡器将用户的请求始终路由到最初创建Session的服务器。虽然简单,但可能限制了服务器的负载均衡效果。 在实际应用中,选择哪种方案取决于...

    session session session szsessdifn

    Session机制是服务器端存储用户特定信息的一种方式,它允许开发者在多个页面之间保持用户状态,解决了HTTP协议无状态的问题。"szsessdifn"可能是某种特定的Session变量名或函数,但在这里没有足够的上下文来详细解释...

    nginx反向代理导致session失效的问题解决

    一同事求援:后台系统的登录成功了,但不能成功登进系统,仍然跳转到... proxy_pass http://192.168.40.159:8081/health/; #无问题的配置 } location /health-dev/ { proxy_pass http://192.168.40.202:8080/health/;

    38. Spring Boot分布式Session状态保存Redis【从零开始学Spring Boot】

    然而,在分布式环境下,传统的基于HTTP Session的状态管理方式会遇到问题,因为每个服务器都无法直接访问其他服务器上的Session,这就需要我们实现一种分布式Session管理方案。本文将基于Redis来探讨如何在Spring ...

    java后台请求http并保持Session

    在Java编程中,后台请求HTTP并保持Session是一个常见的任务,特别是在需要访问受保护的Web资源时,例如登录后的网页数据。下面将详细讲解这个过程,包括GET和POST方法的使用,以及Session管理。 首先,我们需要了解...

    WebLogic Clusters Session_v1.doc

    WebLogic支持两种主要的Http Session复制方式: - **内存中复制(in-memory replication)**:这种模式下,session对象存储在集群内各个实例的内存中,并实时同步。适用于对响应时间要求较高的场景,但可能会消耗更...

Global site tag (gtag.js) - Google Analytics