HTTP cookie
也被称作cook
,最初用于在客户端会话信息,这个规范要求服务器在响应HTTP
请求时,通过发送set-CookieHTTP
头部包含会话信息.如下是包含这个头部的HTTP
响应示例:
注意:CSDN博客就是使用这种模式,可以打开控制台>Network查看
这个
HTTP
响应示例设置了一个名为uuid_tt_dd
,等号后面为值得cookie
.名和值在发送时都会经过URL
解码,浏览器会储存这些会话信息,并且在之后的每个请求中都会通过HTTP
头部cookie
再将它们发回服务器.比如:
这些发送回服务器的额外信息可用于唯一标识发送请求的客户端.
0.cookie的限制
cookie
是与特定域绑定的.设置cookie
后,它会被与请求一起发送到创建它的域.这个限制能保证cookie
中存储的信息只对被认可的接受者开放,不被其他与访问.- 因为
cookie
存储在客户端机器上,所以保证它不会被恶意利用,浏览器会施加限制.同时,cookie
也不会占用太多磁盘空间.
通常,只要遵守以下大致的限制,就不会再任何浏览器中碰到问题:
- 不超过300个cookie;
- 每个cookie不超过4096字节;
- 每个域不超过20个cookie;
- 每个域不超过81920字节;
每个域能设置的
cookie
总是也是受限的,但不同浏览器的限制不同.例如:
- 最新版IE和Edge限制每个域不超过50个cookie;
- 最新版Firefox限制每个域不超过150个cookie;
- 最新版Opera限制每个域不超过180个cookie;
- Safari和Chrome对每个域的cookie数没有硬性限制
- 如果总数超过单个域上限,浏览器会删除之前设置的
cookie
.IE
和Opera
会按照最近最少使用原则删除,为新cookie
腾空间.Firefox
好像会随机删除,因此为避免不确定的风险,最好不要超出限制. - 浏览器会限制
cookie
的大小,大多浏览器对cookie
的限制是不超4096字节,为了跨浏览器兼容,最好不超过4095字节(上下一个字节误差).这个大小限制适用于一个域的所有cookie
而非单个.
1.cookie的构成
cookie
在浏览器中是由以下参数构成的:
- 名称:唯一标识cookie的名称,必须经过URL编码,不分大小写,但最好区别大小写.
- 值:存储在cookie的字符串,必须经过URL编码
- 域:cookie有效的域,发送到这个域的所有请求都会包含对应的cookie.这个值可能包含子域(如www.wrox.com),也可以不包含(如:wrox.com表示对wrox.com的所有子域都有效).如果不明确设置,默认设置cookie的域.
- 路径:请求URL中包含这个路径才会把cookie发送到服务器
- 过期时间:表示什么时候删除cookie的时间戳(即什么时间不发送给服务器),默认会话结束删除所有cookie,可以指定删除时间,这个值是GMT格式,这样关闭浏览器也会留在用户机器上.将时间设置为过去的事件会删除cookie.
- 安全标志:设置之后,只会使用SSL安全连接的情况下才会把cookie发送到服务器.例如,请求https://www,wrox.com会发送cookie,而请求http://www,wrox.com则不会.安全标志是cookie中惟一的非名/值对,只需一个secure就可以.
域、路径、过期时间和安全标志用于告诉浏览器什么时候在请求中包含cookie。这些参数并不会随便随请求发送给服务器,实际发送的只有cookie的名、值对。
2.JavaScript中的cookie
在
JavaScript
中处理cookie
比较麻烦,因为接口比较简单,只有BOM
的document.cookie
属性.根据使用方法不同,该属性的表现迥异,要使用该属性获取值时,document.cookie
返回包含页面中所有有效cookie
的字符串(根据域、路径、过期时间和安全设置),以分号分隔,如下例子:
所有名和值都是URL编码的,因此必须使用
decodeURIComponent()
解码.
在设置值时,可以通过
document.cookie
属性设置新的cookie
字符串.这个字符串在被解析后会添加到原有的cookie
中.设置document.cookie
不会覆盖之前存在的任何cookie
,除非设置了已有的cookie
.设置格式与set-Cookie
头部的格式一样,在这些参数中只有名和值时必须的
这行代码会创建一个名为’
name
‘的会话cookie
,值为’any
’,这个cookie
在每次客户端向服务器发送请求时都会被带上,在浏览器关闭时会被删除.虽然这样直接设置也可以,因为不需要在名称或值中编码任何字符,但最好还是使用encodeURIComponent()
对名和值进行编码
要为创建的cookie指定额外的信息,只要像
set-Cookie
头部一样直接在后面追加相同的字符串即可
因为在
JavaScript
中读写cookie
不是很直观,所以可以通过辅助函数来简化响应的操作,与cookie
相关的基本操作有读、写和删除。这些在CookieUtil
对象中表现如下:
class CookieUtil {
// CookieUtil.get()方法用于取得给定名称的coookie值
static get(name) {
// 为此,需要在document.cookie返回的字符串查找是否存在后面加上等号
let cookieName = `${encodeURIComponent("name")}=`,
cookieStart = document.cookie.indexOf(cookieName),
cookieValue = null;
// 如果找到了再查找该位置后面的分号(便是该cookie的末尾)
// 如果没有找到分号,说明这个cookie在字符串末尾
// 因此字符串剩余部分都是cookie的值.取得cookie后解码返回
//如果没有找到返回null
if (cookieStart > -1) {
let cookieEnd = document.cookie.indexOf(';', cookieStart);
if (cookieEnd == -1) {
cookieEnd = document.cookie.length
}
cookieValue = decodeURIComponent(document.cookie.substring(cookieStart
+ cookitName.length), cookieEnd)
}
return cookieValue
}
// CookieUtil.set()方法用于设置页面上的cookie,接收多个参数
// 这些参数只有前两个是必需的
//在方法内部使用了encodeURIComponent()对名和值进行编码,然后再依次检查
static set(name, value, expires, path, domain, secure) {
let cookieText = `${encodeURIComponent("name")}=${encodeURIComponent("value")}`
// 如果expires参数是Date对象,则使用Date对象的toGMTString()
// 方法添加一个expires选项来获得正确的日期格式
if (expires instanceof Date) {
cookieText += `; expires=${expires.toGMTString()}`
}
// 剩下的代码就是简单的追加cookie字符串,最终设置给document.cookie
if (path) {
cookieText += `;path=${path}`
}
if (domain) {
cookieText += `;domain=${domain}`
}
if (secure) {
cookieText += `;secure`
}
document.cookie = cookieText
}
// 没有直接删除已有cookie的方法,为此需要再次设置同名cookie(相同路径、
// 域和安全选项),日期要选过去的时间
// CookieUtil.unset()方法实现了这些处理.这个方法接收四个参数
// 要删除的cookie名称,可选的路径,可选的域,可选的安全标志
static unset(name, path, domain, secure) {
// 这些参数会传给CookieUtil.unset(),将cookie值设置为空字符串
// 过期日期设置为1970年1月1日(以0毫秒初始化的Date对象的值)
CookieUtil.set(name, '', new Date(0), path, domain, secure)
}
}
- 可以像下面这样使用这些方法:
- 设置cookie
CookieUtil.set('name','山竹回家了')
- 读取cookie
alerf(CookieUtil.get('name'))
- 删除cookie
CookieUtil.unset('name')
- 设置路径/域/过期时间的cookie
CookieUtil.set('name', '山竹回家了','/books/projs/', 'www.wrox.com',
new Date('january 1,2010'))
- 删除刚刚设置的cookie
CookieUtil.unset('name', '/books/projs/', 'www.wrox.com')
- 设置安全cookie
CookieUtil.set('name', '山竹回家了', null, null, null, true)
3.使用cookie的注意事项
- 还有一种叫做
HTTP-only
的cookie.HTTP-only
可以在浏览器设置,也可以在服务器设置,但只能在服务器上读取,这是因为JavaScript
无法取得这种cookie的值.- 因为所有cookie都会座位请求头部由浏览器发送给服务器,所以在cookie中保存大量信息可能会被影响特定浏览器请求的性能.保存的cookie越大,请求完成的事件就越长.即使浏览器对cookie大小有限制,最好还是尽可能只通过cookie保存必要信息,以避免性能问题
- 对cookie的限制及其特性决定了cookie并不是存储大量数据的理想方式,因此,有机会会再讲些其他客户端存储技术.
4.注意
不要在cookie中存储重要或敏感的信息,cookie数据不是保存在安全的环境中,因此任何人都可能获得,应避免把信用卡号或个人地址等信息保存在cookie中.