HTTP Cookie学习笔记

cookie是什么?是饼干,小甜点?

No! No! No! 我今天要总结的cookie并不是你所想的小甜心,我这里要说的cookie是Web开发中的一个重要的“武器”,每一个Web开发者的武器库中肯定要装备这门武器。

cookie是浏览器存储在用户电脑上的一个文本文件,里面包含一些key=value格式的数据;浏览器按照一定的规范来管理和存储这些数据,并在之后的请求中将这些信息发送至服务器,服务器根据客户端传回的cookie数据进行用户识别、用户行为分析等操作。千言万语总结成一句话,cookie就是:

cookie是浏览器存储在用户电脑上的一些数据;每次发起请求时,浏览器都会将对应的cookie数据一起发送至服务器。

为什么要cookie?

HTTP协议是无状态的,也就是说客户端和服务器端不需要建立持久的连接。由于客户端和服务器的连接是基于一种请求应答模式,及客户端和服务器建立一个连接,客户端提交一个请求,服务器端收到请求后返回一个响应,然后二者就断开连接。

既然客户端和服务器在完成一次请求以后,彼此就断开了连接,二者之间就不再有任何关系了;比如,用户在页面一进行了登录,当用户跳转到了同一个Web应用的页面二,那么如何在页面二知道用户已经进行了登录呢?It’s a question!!! 当客户端再次发起请求的时候,服务器端如何判断两次不同的请求来自同一个客户端呢?

是的,服务器无法区分每一次请求之间的联系。这就需要有一个状态来标识每一次请求,如果两次请求的状态标识是一样的,这就表明这两个请求是从同一个客户端发起的。

现在问题的焦点就是这个用来标识每一次请求的状态位如何来设计呢?这的确是一个难题,于是上帝派出了一位青年才俊的工程师来帮程序猿解决了这个问题,他就是24岁的网景公司的moutulli,他设计出了cookie的雏形。

在moutulli设计的基础上,经过多年的发展,cookie的发展的越来越规范,后来直接成为了标准。至于客户端浏览器和服务器之间到底怎么使用cookie,请继续阅读以下内容。

cookie的工作原理

下面我通过浏览器向www.baidu.com发起请求,并简单的将cookie的工作原理图绘制出来。

  1. 当我首次向百度发起首次请求时,请求头如下:

    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:www.baidu.com
  2. 当请求到达百度的服务器以后,百度的服务器需要生成响应,并会在响应的头部写入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.baidu.com; path=/
    Set-Cookie:BDSVRTM=172; path=/

    服务器通过发送一个带有Set-Cookie的HTTP消息响应头来创建一个cookie,并设置cookie的一些属性。

  3. 当客户端浏览器接收到响应头以后,会将cookie信息写入本地进行管理
  4. 当再次向百度服务器发起请求时,客户端会将之前写入的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:www.baidu.com

    客户端通过发送一个带有Cookie: name=value;
    name2=value2
    的HTTP请求头来向服务器发送本地的cookie数据。

  5. 服务器接收到请求以后,从请求头中获得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,那么浏览器中的cookie肯定会很多,那么浏览器如何管理这些cookie呢?这的确是一个问题。

首先,各大浏览器都对cookie的总个数和总大小都有限制(数据来源网络,未做验证):

主流浏览器 IE6.0 IE7.0/8.0 Opera Firefox Safari Chrome
cookie个数 每个域为20个 每个域为50个 每个域为30个 每个域为50个 没有个数限制 每个域为53个
cookie大小 4095个字节 4095个字节 4096个字节 4097个字节 4097个字节 4097个字节

总之,在进行cookie操作的时候,应该尽量保证cookie个数小于20个,总大小小于4KB。

除了个数和大小的管理以外,每个站点各自的写的cookie,浏览器又如何管理呢?我们在服务器端创建一个cookie的时候,一般都会指定以下两个选项:

  • domain选项
  • path选项

这两个选项决定了创建的cookie属于哪个域名下的哪个位置。对于domain选项,默认情况下,domain会被设置为创建该cookie的页面所在的域名,所以当给相同域名发送请求时,该cookie会一起被发送至服务器。比如百度这样的大站,有很多的二级域名,例如:http://music.baidu.com/http://picture.baidu.com/等,如果需要在所有的二级域名下都记录一个cookie,则需要在创建cookie的时候,将cookie的domain选项设置为baidu.com;此时域名为baidu.com下的所有二级域名都将拥有同样的一个cookie。创建域名时指定domain,这又是一个难点,经常会出现顶级域名和二级域名的cookie冲突问题。

我们在发送请求时,浏览器会把domain的值与请求的域名做一个尾部比较(即从字符串的尾部开始比较),并将匹配的cookie发送至服务器。所以以后在设计哪些数据需要写入cookie的时候,也要考虑清楚这个域名的问题。对于此,基本上总结为以下三点:

  • 当我们未指定domain时,默认的domain为用哪个域名访问就是哪个。如果是顶级域名访问,那么设置的cookie也可以被其他二级域名所共享,因此登录等操作一般都在顶级域名下进行操作。
  • 二级域名可以读取设置了domain为顶级域名或者自身的cookie,但是不能读取其他二级域名domain的cookie,因此想要cookie在多个二级域名中共享的时候,需要设置domain为顶级域名,这样就可以在所有二级域名里面使用该cookie,这里需要注意的是顶级域名只能获取到domain设置为顶级域名的cookie,无法获取domain设置为二级域名的cookie。
  • 顶级域名的cookie在顶级域名或者二级域名都可以删除,但是非顶级域名访问的网站要删除顶级域名的cookie的时候,必须要设置获取到的cookie的domain为顶级域名,这样才能删除掉顶级域名的cookie,否则会无法删除。这里默认是删除访问的域名下对应的cookie,而不是顶级域名的那个。

举个例子来说:

  • 我通过浏览器访问http://www.jellythink.com,请求到达服务器以后,我创建cookie时,指定的domain只能是www.jellythink.com、.jellythink.com或者jellythink.com
  • 而当我通过浏览器访问http://picture.jellythink.com,请求到达服务器以后,我创建cookie时,指定的domain只能是picture.jellythink.com、.jellythink.com或者jellythink.com

说完domain,再来说说path选项。 在创建cookie的时候,也可以指定一个path值,path选项指定了请求的资源URL中只有在存在指定的路径时,才会发送Cookie消息头,它决定了客户端发送cookie到服务器端的匹配规则。通常是将path选项的值与请求的URL从头开始逐字符比较,如果字符匹配,则发送Cookie消息头。需要注意的是,只有在domain选项满足之后才会对path属性进行比较。path属性的默认值是发送Set-Cookie消息头所对应的URL中的path部分。

以上从浏览器本身的限制和生成cookie时的选项对cookie的管理进行了简单的总结。接下来就通过一些简单的代码来演示如何创建和获取cookie。

创建cookie

服务器通过发送一个带有Set-Cookie的HTTP消息响应头来创建一个cookie。例如:

// 创建一个cookie对象
Cookie co = new Cookie("site", "http://www.jellythink.com");
co.setDomain("test.com");

// 通过响应头,将cookie发送到客户端
response.addCookie(co);

创建cookie本身没有多少难点,但是在创建创建cookie的时候,我们需要明白几个选项,以及这些选项的具体作用。

名称 作用
domain选项 请参见【cookie的管理】这一小节
path选项 请参见【cookie的管理】这一小节
maxage选项 设置浏览器何时删除cookie
secure选项 Secure字段告诉浏览器在https通道时,对Cookie进行安全加密,这样即时有黑客监听也无法获取cookie内容;默认情况下,在HTTPS连接上传输的cookie都会被自动添加上secure选项。当secure值为true时,cookie在HTTP中是无效,在HTTPS中才有效
httponly选项 HttpOnly字段告诉浏览器,只有在HTTP协议下使用,对浏览器的脚本不可见,所以跨站脚本攻击时也不会被窃取,此时JS则无法访问带有httponly的cookie

示例代码:

Cookie co = new Cookie("site", "http://www.jellythink.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请求头超长的问题。

请求到达服务器端以后,我们可以这样读取cookies。

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 + " &nbsp; Cookie值:" + value + "<br>");
     }
}

总结

cookie作为每个Web开发人员必需要会的知识点,其中的细节有很多,而且经常得不到重视。这篇文章就对Web开发中的cookie这个知识点进行了详细的总结,每个容易忽视的细节,每个知识点都进行了详细的分析,虽然理论知识偏多,但是这些理论知识却是实践开发的基石,希望你能喜欢这篇文章。

时间: 2024-10-09 05:35:35

HTTP Cookie学习笔记的相关文章

Cookie学习笔记(三)

11.4.3  删除会话变量 在使用会话时,需要创建一个方法来删除会话数据.在当前示例中,当用户注销时,这是必要的. 虽然cookie系统只需要发送另一个cookie来销毁现有的cookie,但是会话的要求更高,因为既要考虑客户上的cookie,又要考虑服务器上的数据. 要删除单独一个会话变量,可以使用unset()函数(它可以处理PHP中的任何变量): unset($_SESSION['var']); 要删除每个会话变量,可以重置整个$_SESSION数组: $_SESSION = array

Cookie学习笔记(一)

Cookie 简介 一.简介     说起来,Cookie应该是一种应用较久的技术了.早在HTML刚刚出现的时候,在每个独立的页面之间没有办法记录和 标识不同的用户.后来人们就发明了Cookie技术,当用户访问网页时,它能够在访问者的机器上创立一个文件,我们把它叫作Cookie,写一段内容进去,来标识不同的用户.如果下次用户再访问这个网页的时候,它又能够读出这个文件里面的内容,这样网页就知道上次这个用户已经访问过该网页了.      虽然现在网页的制作技术比起几年以前已经发展了许多.不过有些时候

Cookie学习笔记二:Cookie实例

今天说说刚刚学到的两个Cookie的最经典应用:自动登录和购物车设置 一:自动登录 需要两个页面:login.jsp与index.jsp,login.jsp用来输出登录信息,index.jsp处理登录信息:如果有Cookie,则自动登录,否则创建输入信息的对象的Cookie,下次登录可以直接登录,但是我们在这里给Cookie设置一个最大保存时间30s,即登录30s后会自动退回到登陆页面,具体代码如下: login.jsp: <%@ page language="java" con

Cookie学习笔记

会话的概念: 打开浏览器,输入正确的URL访问服务器, 期间浏览器向服务器请求资源,服务器给予资源响应,最后关闭浏览器,客户端和浏览器的连接断开.这一过程可理解为会话. Cookie入门: Cookie是在服务器创建,保存在客户端.Cookie会在客户端保存一些用户的信心,比如浏览信息.在客户端没有删除一个站点的Cookie情况下,在下一次在访问该站点的时候会在请求头中带有Cookie信息发给服务器,以便于服务端做出更为合理的处理. 每个网站只能读取自己的Cookie,不能读取别的网站的Cook

js Cookie 学习笔记

<1>设置cookie <script type="text/javascript"> window.onload=function(){ document.cookie="myName=C_world"; } <script> <2>获取cookie <script type="text/javascript"> window.onload=function(){ var myName

cookie 学习笔记

SESSION:每个浏览器有自己的一个独一无二的编号,服务器通过此识别不同的浏览器 COOKIE:服务器端写到客户端的一些小文本信息 cookie是一个名值段,结构有些像map,它记录着服务端与客户端之间的一些信息,由此客户端再去访问服务端信息的时候可以从本地直接获取一些信息二不用再间接访问服务器(所以某些网站没了cookie是不可以正常使用的). 举个例子,有时候访问一个网页两星期之内不用再去输入登录名与密码,这时候这些信息会记录在cookie里面(两星期后自动删除)

Session、Cookie 学习笔记

在开始今天的博文之前首先为自己庆祝一下自己有了三个粉丝,也有了同僚的评论,说实话因为这个开心了好久!哈哈,好了在开始今天的正题之前,首先大家需要了解以下几点: a. HTTP 协议是无状态的协议,WEB 服务器本身不能识别出哪些请求是同一个浏览器发出的,浏览器的每一次请求都是孤立的; b. 作为服务器必须能够采用一种机制来唯一标识一个用户,同时记录该用户的状态; c. WEB 应用中的会话是指一个客户端浏览器与 WEB 服务器之间连续发生的一系列请求和响应过程; d. WEB 应用的会话状态是指

[原创]java WEB学习笔记30:Cookie Demo 之显示最近浏览的记录

本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 ---------------------------------

Spring MVC 学习笔记(二):@RequestMapping用法详解

一.@RequestMapping 简介 在Spring MVC 中使用 @RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些URL请求,相当于Servlet中在web.xml中配置 <servlet>     <servlet-name>servletName</servlet-name>     <servlet-class>ServletClass</servlet-class> </servlet>