Cookie的类型

会话cookie和持久cookie

会话cookie是一种临时cookie,它记录了用户访问站点时的设置和偏好,当用户退出浏览器时,会话cookie就会被删除。

持久cookie的生存时间更长一些,它存储在用户的硬盘上,浏览器退出或计算机重启时他们仍然存在。

会话cookie与持久cookie之间的唯一区别就是它们的过期时间。

如果设置了Discard参数(cookie版本1中的参数),或者没有设置Expires或者Max-Age参数(cookie版本1中的参数)来说明扩展的过期时间,这个cookie就是一个会话cookie。

Cookie是如何工作的

Cookie可以通过服务器进行设置,相当于服务器给用户贴的一个标签,用于跟踪用户的状态。

通过服务器设置的cookie信息通过响应头返回给浏览器,浏览器将响应头中的cookie信息保存在本地,当下次向服务器发送HTTP请求时,就自动将保存的这些cookie信息添加到请求头中(包含通过document.cookie接口设置的cookie)。

下面是退出博客园登录时的响应头和请求头,响应头中有Set-Cookie字段,请求头中有Cookie字段:

通过BOM提供的document.cookie接口,在前端可以对cookie进行操作(增、删、改),本质上是对符合一定规律的一个字符串进行操作,这样开发人员就可以利用cookie在本地存储一些数据。当然,建议存储一些非敏感信息。

Cookie的限制和组成

Cookie的限制

Cookie的限制主要有两条:

  1. 访问cookie时的同源限制
  2. Cookie的个数和尺寸限制

同源限制

Cookie在性质上是绑定在特定的域名下的。当创建了一个cookie后,再给创建它的域名发送请求时,请求头中都会包含这个cookie。这个限制确保了储存在cookie中的信息只能让批准的域访问,而无法被其他域访问。

个数和尺寸限制

每个域名下可绑定的cookie的个数是有限的,不同浏览器所限制的个数不同。

浏览器对同域名下cookie个数的限制见下表:

浏览器

可绑定的cookie的个数

IE6

20

IE7

50

Firefox

50

Opera

30

Safari

没有硬性限制

Chrome

没有硬性限制

当超过单个域名限制之后还要再设置cookie,浏览器就会清除以前设置的cookie。

浏览器中对于单个cookie的尺寸也有限制,一般限制在4KB。尺寸限制影响到一个域名下的所有cookie,而并非每个cookie单独限制。

Cookie的组成

名称和值 name = value:必填。name和value都是字符序列,除非包含在双引号内,否则不包括分号、逗号、等号和空格。Web服务器可以创建任意的name=value关联,浏览器在后继对站点的访问中会将其送会给web服务器。

域  domain:可选。表示该cookie对于哪个域是有效的。所有向该域发送的请求中都会包含这个cookie信息。这个值可以包含子域(如www.wrox.com,表示该cookie信息只向该域名发送),也可以不包含(如.wrox.com,则对于wrox.com的所有子域都有效)。如果没有明确规定,那么这个域会被认作来自设置该cookie的那个服务器所在的域。

路径  path:可选。通过这个字段可以为服务器上特定的文档分配cookie。如果path字段是一个URL路径前缀,就可以附加一个cookie。例如:路径 /foo与 /foobar和 /foo/bar.html相匹配。路径 / 与域名中的所有内容都匹配。默认值是设置 Cookie 时的当前目录。

失效时间  expires(新版的cookie规范中是max-age字段):可选。这个字段会指定一个日期字符串,用来定义cookie的实际生存期。一旦到了这个日期,就不再存储或发布这个cookie了,该cookie就会被删除。如果设置的日期是以前的时间,则cookie会被立刻删除。

日期格式为GMT格式:Wdy, DD-Mon-YYYY HH:MM:SS GMT。

安全标志  secure:可选。该字段不是键值对的形式,如果要指定该字段,只要在设置cookie时添加secure字符即可。设置了该字段后,该cookie只有在使用SSL连接的时候才发送到服务器。例如:指定域为www.wrox.com的cookie,在制定了secure字段后,该cookie只能发送给https://www.wrox.com,而发送给http://www.wrox.com的请求不会添加该cookie。

HTTP专用  HttpOnly:可选。该字段只能在服务端设置,表示该cookie是否能通过JS(BOM的document.cookie接口)去访问。默认情况下HttpOnly字段为空,表示可以通过JS访问该cookie。

按照规范,开发人员无法利用JS在前端修改cookie的HttpOnly字段,不过有的浏览器没有这个限制,具体看这篇文章:浏览器中因cookie设置HttpOnly标志引起的安全问题

关于如何在服务端设置该字段,请看这篇文章:关于Cookie安全性设置的那些事

注意:域、路径、失效时间、安全标志(secure)和HttpOnly字段都是服务器给浏览器的指示,告诉浏览器如何存储和发送cookie,这些参数并不会作为发送到服务器的cookie信息的一部分,只有cookie中的名值对儿(name=value)才会被发送。

在前面的图片中,响应头中的一个Set-Cookie就代表一个cookie;请求头中的Cookie字段中可以包含多个cookie的名值对儿,而不是仅包含一个cookie的名值对儿。

BOM的document.cookie接口

当用来获取cookie时,document.cookie返回当前页面可用的所有cookie的字符串,一系列由分号隔开的名值对儿。

例如,我在Chrome中打开这个页面:https://segmentfault.com/a/1190000004556040,在控制台中输入以下代码:

console.log(document.cookie);

控制台中会输出以下结果:

PHPSESSID=web2~f57e474e4a8mc396h4du05qsa0;
Hm_lvt_e23800c454aa573c0ccb16b52665ac26=1495500966;
Hm_lpvt_e23800c454aa573c0ccb16b52665ac26=1495500966;
_ga=GA1.2.1399344530.1495500966;
_gid=GA1.2.584865054.1495500966;
showRegister2=true;
showRegister=false

有七个由分号分隔得名值对儿,表示有七个cookie可用(所有名字和值都是经过URL编码的,所以必须使用decodeURIComponent()来解码。)。

点击开发者工具中的Application选项,在左边找到Cookies下拉菜单,点击第一个域名,就可以看到这七个cookie的详细信息。具体如下:

当用于设置cookie时,document.cookie可以设置一个新的cookie字符串,这个cookie字符串会被解释并添加到当前现有的cookie集合中。其中名值对儿(name=value)是必须的(最好用encodeURIComponent()对name和value进行编码),其它字段在cookie的组成部分已做过介绍。

通过document.cookie设置的cookie并不会覆盖现有的cookie,除非设置的cookie的name在现有cookie集合中已经存在,并且path/domain/secure这几个选项一定要和旧cookie 保持一样。否则不会修改旧cookie,而是添加了一个新的 cookie。

例子(使用wamp环境):

PHP代码:

<?php setcookie("abc", "test",null, '/' );   ?>

HTML代码:

<button id="btn" type="button" value="submit">发送请求</button>
<button id="display-cookie" type="button" value="submit">显示cookie</button>
<button id="reset-cookie" type="button" value="submit">设置cookie</button>

JS代码:

function myAJAX(url) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
if((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
console.log(xhr.responseText);
console.log(xhr.responseXML);
} else {
console.log(xhr.statusText);
console.log(xhr.status);
}
}
};
xhr.open("get",url,true);//true表示异步,false表示同步
//此处设置头部信息 xhr.send(null);
}
function init(){
var btn = document.getElementById('btn');
var displayCookie = document.getElementById('display-cookie');
var resetCookie = document.getElementById('reset-cookie');
var removeCookie = document.getElementById('remove-cookie');
btn.addEventListener('click',function(event) {
var url = 'cookie.php';
myAJAX(url);
},false); displayCookie.addEventListener('click',function(event) {
console.log(document.cookie);
},false); resetCookie.addEventListener('click',function(event) {
document.cookie = "abc=ok;path=/"
},false);
}
init();

第一次打开该页面时,点击显示cookie按钮,控制台无输出内容,谷歌开发者工具中Application选项卡中的cookie选项中也为空。

点击发送请求按钮,在Network选项卡中查看头部信息:

在Application选项卡中的cookies选项查看cookie:

现在点击显示cookie按钮:

只显示出了名值对儿,没有显示该cookie的其它字段的信息。

接下来点击设置cookie按钮,重设该cookie,然后再点击显示cookie按钮:

该cookie的值被重设为了ok。

我们再点击发送请求按钮,看看这一次请求的头部信息:

请求头中的Cookie字段是浏览器发送给服务器的cookie信息,cookie的值之前被我们设置为了ok。响应头中的Set-Cookie字段是服务器返回给浏览器的cookie信息(实际上这时,cookie的值又被设置为了test)(我只是描述这个现象,不知道理解的对不对。)。

没有删除已有cookie的直接方法。所以,需要使用相同的路径(path)、域(domain)和安全选项(secure)再次设置原cookie,并将失效时间设置为过去时间

通过document.cookie设置的cookie也会被浏览器添加到请求头中。

举例,用document.cookie设置cookie:

document.cookie = encodeURIComponent(“username”) + “=” +
encodeURIComponent(“jack”) + “; domain=.wrox.com; path=/”;

子cookie

子cookie是存放在单个cookie中的更小段的数据。也就是使用cookie值来存储多个名值对儿。

一种子cookie的格式:

name=name1=value1&name2=value2&name3=value3&name4=value4

本质上还是字符串的操作。

CORS中的cookie

(摘自阮一峰老师的文章:跨域资源共享 CORS 详解

CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials字段为true。另一方面,开发者必须在AJAX请求中打开XMLHttpRequest对象的withCredentials属性。否则,即使服务器同意发送Cookie,浏览器也不会发送。或者,服务器要求设置Cookie,浏览器也不会处理。

但是,如果省略withCredentials设置,有的浏览器还是会一起发送Cookie。这时,可以显式关闭withCredentials。

需要注意的是,如果要发送Cookie,Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名。同时,Cookie依然遵循同源政策,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且(跨源)原网页代码中的document.cookie也无法读取服务器域名下的Cookie。

写在后面的话:

上面关于cookie的总结,仅仅是我了解到的关于cookie的知识。

关于cookie的规范:

https://tools.ietf.org/html/rfc6265

参考文章:

1、聊一聊 cookie

2、http://php.net/manual/zh/function.setcookie.php

3、HTTP权威指南第11章

4、Javascript高级程序设计(第三版)第23章

相关文章:

1、漫谈Cookie安全

2、Cookie/Session机制详解

3、Document.cookie MDN

关于Cookie的知识的总结的更多相关文章

  1. web跨域及cookie相关知识总结

    原文:web跨域及cookie相关知识总结   之前对于跨域相关的知识一致都很零碎,正好现在的代码中用到了跨域相关的,现在来对这些知识做一个汇总整理,方便自己查看,说不定也可能对你有所帮助. 本篇主要 ...

  2. Session & Cookie小知识~

    Cookie 一个HTTP cookie的(也称为网络Cookie,互联网的cookie,浏览器cookie,或者干脆饼干)是一小块从发送的数据的网站用户的并存储在用户的计算机上的网页浏览器,而用户浏 ...

  3. session和cookie相关知识总结

    HTTP协议本身是无状态的,这与HTTP协议本来的目的是相符的,客户端只需要简单的向服务器请求下载某些文件,无论是客户端还是服务器都没有必要纪录彼此过去的行为,每一次请求之间都是独立的. 人们很快发现 ...

  4. session和cookie的知识总结

    1.HTTP协议 由HTTP客户端发起一个请求,建立一个到服务器指定端口(默认是80端口)的TCP连接.HTTP服务器则在那个端口监听客户端发送过来的请求.一旦收到请求,服务器(向客户端)发回一个状态 ...

  5. JavaScript 操作 Cookie

    转自作者:聂微东出处:http://www.cnblogs.com/Darren_code/      什么是 Cookie “cookie 是存储于访问者的计算机中的变量.每当同一台计算机通过浏览器 ...

  6. cookie的一些细节

    什么是 Cookie “cookie 是存储于访问者的计算机中的变量.每当同一台计算机通过浏览器请求某个页面时,就会发送这个 cookie.你可以使用 JavaScript 来创建和取回 cookie ...

  7. JavaScript之Cookie讲解

    什么是 Cookie “cookie 是存储于访问者的计算机中的变量.每当同一台计算机通过浏览器请求某个页面时,就会发送这个 cookie.你可以使用 JavaScript 来创建和取回 cookie ...

  8. Cookie介绍及JavaScript操作Cookie方法详解

    本文主要为大家简单介绍了以下Cookie的用途.运行机制,以及JavaScript操作Cookie的各种方法,总结的比较全面,希望能给大家带来帮助. 什么是 Cookie “cookie 是存储于访问 ...

  9. Cookie概念

    ASP.NET Cookie概念.CURD操作.原理.实际运用   会话就WEB开发来说,一个会话就是你通过浏览器与服务器之间的一次通话,只不过这种通话是以用浏览器浏览的方式来实现的. 就会话的应用来 ...

随机推荐

  1. Java集合总结系列2:Collection接口

    Collection 接口是 Java 集合类的一个根接口,Java 在 Collection 接口中定义了许多通用的数据操作类方法以及判断类方法. 通过查看 API 文档或源码的方式,我们可以了解到 ...

  2. vuejs学习笔记(1)--属性,事件绑定,ajax

    属性 v-for 类似于angular中的 ng-repeat ,用于重复生成html片段: <ul id="box"> <li v-for="(v, ...

  3. linux redis安装

    redis官网地址:http://www.redis.io/ 在Linux下安装Redis非常简单,具体步骤如下(官网有说明): 1.下载源码,解压缩后编译源码. $ wget http://down ...

  4. java 解压 zip 包并删除

    需求是这样的,  在服务器上有 运营上传的zip 包,内容是用户的照片,我需要做的是 获取这些照片上传,并保存到 数据库. 这里面的 上传照片,保存数据库都不难,主要问题是解压zip包,和删除zip ...

  5. AJAX载入外部JS文件到页面并让其执行的方法(附源码)

    一. 向HTML页面中动态添加JS文件(从外部载入)并让其执行的两种方法 1.只适用于IE浏览器的简单方法: 先在文档中放置一张JS"空床"并添加ID:<script id= ...

  6. idea + mybatis generator + maven 插件使用

    idea + mybatis generator + maven 插件使用 采用的是 generator 的 maven 插件的方式 ~ 1 pom.xml mybatis其它配置一样,下面是配置my ...

  7. 使用spring利用HandlerExceptionResolver实现全局异常捕获

    最近一直没有时间更新是因为一直在更新自己使用的框架. 之后会慢慢带来对之前使用的spring+mvc+mybatis的优化. 会使用一些新的特性,实现一些新的功能. 我会尽量分离业务,封装好再拿出来. ...

  8. java多线程基本概述(七)——join()方法

    在很多情况下,主线程创建并启动子线程,如果子线程中有大量的耗时运算,主线程将早于子线程结束,如果想让主线程等待子线程结束后再结束,那么我们可以使用join()方法.调用join()方法的意思是当前线程 ...

  9. java swing组件的一些基本属性

    JLabel get/setText(): 获取/设置标签的文本. get/seticon(): 获取/设置标签的图片. get/setHorizontalAlignment(): 获取/设置文本的水 ...

  10. java复习(9)---数据库JDBC

    java写工程当然需要连接数据库.JDBC技术是连接数据库和应用程序的纽带,本节主要说明如何连接数据库. java中提供sql类. package re09; import java.sql.*; p ...