从一开始迷糊到现在的session和cookie

如果你说你不会session和cookie,学java的人会对你嗤之以鼻,因为那是基础的技术,是面试中简单的问题,在网上有大量资料。但是,这并不是一个简单的问题。因为session这个词在被滥用,我读很多文档时都碰到过session,有时候人们说它是一次会话(会话又是什么?),有时说它是jsp的一个默认作用域,有时又说它是浏览器打开到关闭的一个情况……

关键的问题是,当我们在谈session与cookie时,它指的是什么?

session与cookie刨根问底

RFC2109

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 technique 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.

文档说的很清楚,为了解决http协议的无状态性,我们需要一种技术,这种技术能把http request和http response置于一种更大的上下文中,我们把它叫做session

There are, of course, many different potential contexts and thus many different potential types of session. The designers’ paradigm for sessions created by the exchange of cookies has these key attributes:

  1. Each session has a beginning and an end.
  2. Each session is relatively short-lived.
  3. Either the user agent or the origin server may terminate a session.
  4. The session is implicit in the exchange of state information.

由于上下文有很多种,因此session也有很多种。由cookie来实现的session有几个特点:

  • 每个session有开始有结束
  • 每个session相对短命
  • 客户端和服务端都能终结一个session
  • session在信息交换中是隐式存在的

The origin server initiates a session, if it so desires. (Note that “session” here does not refer to a persistent network connection but to a logical session created from HTTP requests and responses. The presence or absence of a persistent connection should have no effect on the use of cookie-derived sessions). To initiate a session, the origin server returns an extra response header to the client, Set-Cookie.

它说服务端初始化一个session,然后我们一直讲的session是一个逻辑概念,而大家平时讲的session是一种持续的客户端和服务端的网络连接。不管有没有这种连接,都不会影响cookie-derived的session的使用。

A user agent returns a Cookie request header (see below) to the origin server if it chooses to continue a session. The origin server may ignore it or use it to determine the current state of the session. It may send back to the client a Set-Cookie response heade with the same or different information, or it may send no Set-Cookie header at all. The origin server effectively ends a session by sending the client a Set-Cookie header with Max-Age=0.

origin server把cookie放在response header中,user agent回的cookie放在request header中。

语法和解析的细节我就不说了,大家可以自己去查阅文档。


它这里举了一个很好的例子:

    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-Cookie: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"

         Cookie reflects user's identity.

服务端把cookie放在header中。

    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."

用户选了一件商品。user agent回的时候在VersionPath前都加了$,因为origin server在解析的时候会从左往右读,读到不是$开头的信息就找到了该cookie的name(这里是Customer)。

 4.  Server -> User Agent

         HTTP/1.1 200 OK
         Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";
                 Path="/acme"

         Shopping basket contains an item.

购物车里放了商品。

   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.

用户选择支付手段。

6.  Server -> User Agent

         HTTP/1.1 200 OK
         Set-Cookie: Shipping="FedEx"; Version="1"; Path="/acme"

         New cookie reflects shipping method.

header中新添加的cookie反映了使用的支付手段。


     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.

成功,交易结束。

这个例子完美展示了如何通过cookie实现服务端和客户端的交流。


Cookie

上面的是规范,tomcat怎么实现的呢?

javax.servlet.http.Cookie的文档:

/**
 * Creates a cookie, a small amount of information sent by a servlet to a Web
 * browser, saved by the browser, and later sent back to the server. A cookie's
 * value can uniquely identify a client, so cookies are commonly used for
 * session management.
 * <p>
 * A cookie has a name, a single value, and optional attributes such as a
 * comment, path and domain qualifiers, a maximum age, and a version number.
 * Some Web browsers have bugs in how they handle the optional attributes, so
 * use them sparingly to improve the interoperability of your servlets.
 * <p>
 * The servlet sends cookies to the browser by using the
 * {@link HttpServletResponse#addCookie} method, which adds fields to HTTP
 * response headers to send cookies to the browser, one at a time. The browser
 * is expected to support 20 cookies for each Web server, 300 cookies total, and
 * may limit cookie size to 4 KB each.
 * <p>
 * The browser returns cookies to the servlet by adding fields to HTTP request
 * headers. Cookies can be retrieved from a request by using the
 * {@link HttpServletRequest#getCookies} method. Several cookies might have the
 * same name but different path attributes.
 * <p>
 * Cookies affect the caching of the Web pages that use them. HTTP 1.0 does not
 * cache pages that use cookies created with this class. This class does not
 * support the cache control defined with HTTP 1.1.
 * <p>
 * This class supports both the RFC 2109 and the RFC 6265 specifications.
 * By default, cookies are created using RFC 6265.
 */

因为cookie能够用来定位唯一确定的client,所以被用作session管理。

cookie既然能实现客户端和服务端的交流,那为什么要出现其他session技术呢?

因为cookie有缺点。

由于cookie暴露在了浏览器,所以不安全,而且容量小。


JSESSIONID

所以我们要用到HttpSession

public interface HttpSession
Provides a way to identify a user across more than one page request or visit to a Web site and to store information about that user.
The servlet container uses this interface to create a session between an HTTP client and an HTTP server. The session persists for a specified time period, across more than one connection or page request from the user. A session usually corresponds to one user, who may visit a site many times. The server can maintain a session in many ways such as using cookies or rewriting URLs.

This interface allows servlets to
1.View and manipulate information about a session, such as the session identifier, creation time, and last accessed time
2.Bind objects to sessions, allowing user information to persist across multiple user connections

HttpSession与用户一一对应。因此当一个用户登录JD之后,就不用在购物页面、支付页面重复登录了。

HttpSession在这方面与Cookie一模一样,它们都是session的具体实现。

至于关掉浏览器后,cookie是否还在,session是否还在,这个都可以自己写代码试一下。

现在的问题是,HttpSession怎么与一个client一一对应呢?

我们在HttpSession session = request.getSession();上打一个断点,观察浏览器第一次访问时的情况。


一直get。像getBean一样。


create。

这里的manager也是tomcat中的顶级管理接口。


创建session对象。

注意这里:

generateSessionId产生了sessionID,就是那一长串的32个字符的字符串。

服务端创建的session对象:


这个StandardSession就是HttpSessin的一个实现类。

服务端自己创建session之后,还要做一个工作:


他要在这个session的基础之上创建一个cookie。


这个cookie的value就是sessionID的值。

那么这个特殊的cookie的key是多少呢?


那就是神秘的JSESSIONID

也就是说,当浏览器第一次访问服务器的时候,服务端会生成一个sessionID,然后以JSESSIONID作为key,以sessionID的值作为value创建一个cookie,然后添加到header中:


于是,浏览器的JSESSIONID的value就和服务端的sessionID对应了。

我们可以说,HttpSession是建立在Cookie之上的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值