cookie原理说明
什么是 Cookie?
HTTP协议是无状态的,也就是说客户端和服务器端不需要建立持久的连接。由于客户端和服务器端的连接是基于一种请求应答模式,即客户端和服务器建立一个连接-客户端提交一个请求-服务器端收到请求后返回一个响应,然后二者就断开连接。
若客户端和服务器在完成一次请求以后就断开了连接,二者之间就不再有任何关系了;那么,当用户在页面1进行了登录后跳转到了同一个Web应用的页面2时,如何在页面2知道用户已经进行了登录呢?亦即当客户端再次发起请求的时候,服务器端如何判断两次不同的请求来自同一个客户端呢?
HTTP协议下,服务器是无法区分每一次请求之间的联系的。要判断这种联系就需要有一个状态来标识每一次请求,如果两次请求的状态标识是一样的,这就表明这两个请求是从同一个客户端发起的。
Cookie 就是这样一个用来标识每一次请求的状态位。经过多年的发展 Cookie 变得越来越规范,后来直接成为了一个通用标准。
Cookie 的工作原理
-
首次请求:当客户端首次向服务器发起请求时,HTTP请求头如下:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en,zh-CN;q=0.8,zh;q=0.6
Connection:keep-alive
Host:tce.fsphere.c -
服务器响应:请求到达服务器后,服务器生成响应,并在响应的头部写入 Cookie 信息:
Set-Cookie:BD_HOME=1; path=/
Set-Cookie:__bsi=14934756243064632384_00_0_I_R_174_0303_C02F_N_I_I_0; expires=Thu, 19-Nov-15 14:14:50 GMT; domain=www.qcloud; path=/
Set-Cookie:BDSVRTM=172; path=/ -
客户端存储 Cookie:客户端浏览器接收到响应头后,会将 Cookie 信息写入本地进行管理。
-
后续请求:再次向服务器发起请求时,客户端通过发送一个带有
Cookie: name=value; name2=value2
的 HTTP 请求头将之前存储的 Cookie 一起发送过去。请求的头部信息为:Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en,zh-CN;q=0.8,zh;q=0.6
Connection:keep-alive
Cookie:BD_HOME=1; BDSVRTM=0; BD_LAST_QID=1507196234531915875957057
Host:tce.fsphere.c -
服务器处理 Cookie:服务器接收到请求后,从请求头中获取 Cookie 信息,分析 Cookie 数据后向客户端返回响应。
以上就是 Cookie 在客户端和服务器之间进行传递信息的基本过程。
Cookie 的生命周期
Cookie 是有生命周期的。一旦到了 Cookie 的失效日期,客户端的 Cookie 就会被删除。服务器在创建 Cookie 时可以控制一个 Cookie 在客户端“存活”多长时间。以下几种情况下,Cookie 都会结束其生命周期:
-
未指定过期时间的 Cookie:当服务器创建一个 Cookie 时没有指定过期时间,客户端会将这类 Cookie 写入浏览器开辟的一块内存中。当关闭浏览器后,这块内存被释放,对应的 Cookie 也就结束了生命周期。
-
指定过期时间的 Cookie:当服务器创建一个 Cookie 时指定了过期时间,当到达过期时间时,对应的 Cookie 会被删除。
-
浏览器 Cookie 数量达到限制:当浏览器中的 Cookie 数量达到限制时,浏览器会按照某种策略删除一些旧的 Cookie,腾出空间来创建新的 Cookie。
-
人为删除 Cookie:用户也可以手动删除 Cookie。
Cookie 管理
服务器端创建一个 Cookie 时,一般会指定以下两个选项:
-
domain:决定了 Cookie 属于哪个域名。默认情况下,domain 会被设置为创建该 Cookie 的页面所在的域名。当客户端再次给相同域名发送请求时,Cookie 会一起被发送至服务器。
- 未指定 domain 时,默认的 domain 为访问地址的域名。如果是顶级域名访问,设置的 Cookie 也可以被其他二级域名共享。
- 二级域名可以读取设置了 domain 为顶级域名或自身的 Cookie,但不能读取其他二级域名 domain 的 Cookie。如果希望 Cookie 在多个二级域名中共享,需要设置 domain 为顶级域名。
-
path:规定客户端请求的 URL 只有在存在 path 指定的路径时,才会发送 Cookie 消息头。path 决定了客户端发送 Cookie 到服务器端的匹配规则。
- path 的默认值是发送 Set-Cookie 消息头所对应的 URL 中的 path 部分。
- 只有在 domain 选项满足后,才会对 path 属性进行比较。
服务器端创建 Cookie
服务器通过发送一个带有 Set-Cookie
的 HTTP 响应头来创建一个 Cookie。例如:
// 创建一个 Cookie 对象
Cookie co = new Cookie("site", "http://tcecqpoc.fsphere.cn");
co.setDomain("test.com");
// 通过响应头,将 Cookie 发送到客户端
response.addCookie(co);
Cookie co = new Cookie("site", "http://qcloud.com");
co.setDomain("test.com");
co.setPath("/pages");
co.setMaxAge(3600); // 单位为秒
co.setHttpOnly(true);
co.setSecure(false);
response.addCookie(co);
客户端读取 Cookie
客户端向服务器发起请求时,在 domain 和 path 匹配的情况下,会将对应的 Cookie 一起发送到服务器端。如果一个 path 下设置的 Cookie 太多,可能会导致 HTTP 请求头超长的问题。请求到达服务器端后,可以通过以下方式读取 Cookie:
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (int i = 0; i < cookies.length; ++i) {
// 获得具体的 Cookie
Cookie cookie = cookies[i];
// 获得 Cookie 的名称
String name = cookie.getName();
String value = cookie.getValue();
out.print("Cookie名:" + name + " Cookie值:" + value + "<br/>");
}
}