关于Cookie的知识的总结
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于Cookie的知识的总结相关的知识,希望对你有一定的参考价值。
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的限制主要有两条:
访问cookie时的同源限制
Cookie的个数和尺寸限制
同源限制
Cookie在性质上是绑定在特定的域名下的。当创建了一个cookie后,再给创建它的域名发送请求时,请求头中都会包含这个cookie。这个限制确保了储存在cookie中的信息只能让批准的域访问,而无法被其他域访问。
个数和尺寸限制
每个域名下可绑定的cookie的个数是有限的,不同浏览器所限制的个数不同。
浏览器对同域名下cookie个数的限制见下表:
浏览器 | 可绑定的cookie的个数 |
IE6 | 20 |
IE7 | 50 |
Firefox | 50 |
Opera | 30 |
Safari | 没有硬性限制 |
Chrome | 没有硬性限制 |
当超过单个域名限制之后还要再设置cookie,浏览器就会清除以前设置的cookie。
浏览器中对于单个cookie的尺寸也有限制,一般限制在4MB。尺寸限制影响到一个域名下的所有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=; showRegister=
有七个由分号分隔得名值对儿,表示有七个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的知识的总结的主要内容,如果未能解决你的问题,请参考以下文章