zoukankan      html  css  js  c++  java
  • 关于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的限制主要有两条:

    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

  • 相关阅读:
    数据类型及转换
    进制转换
    精通libGDX-RPG开发实战
    github上最好的开源MMORPG
    同步mysql数据到ElasticSearch的最佳实践
    在libGDX中使用Spine骨骼动画
    window下Kafka最佳实践
    linux 系统的负载与CPU、内存、硬盘、用户数监控脚本[marked]
    源码安装cmake(或者叫升级cmake)
    Rust-HayStack
  • 原文地址:https://www.cnblogs.com/fogwind/p/6890159.html
Copyright © 2011-2022 走看看