Cookie -- 前端视角

1.Cookie机制

在程序中,会话跟踪是很重要的事情。理论上,一个用户的所有请求操作都应该属于同一个会话,而另一个用户的所有请求操作则应该属于另一个会话,二者不能混淆。例如,用户A在超市购买的任何商品都应该放在A的购物车内,不论是用户A什么时间购买的,这都是属于同一个会话的,不能放入用户B或用户C的购物车内,这不属于同一个会话。

而Web应用程序是使用HTTP协议传输数据的。HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。即用户A购买了一件商品放入购物车内,当再次购买商品时服务器已经无法判断该购买行为是属于用户A的会话还是用户B的会话了。要跟踪该会话,必须引入一种机制。

Cookie就是这样的一种机制。它可以弥补HTTP协议无状态的不足。在Session出现之前,基本上所有的网站都采用Cookie来跟踪会话。

2.什么是Cookie

Cookie意为“甜饼”,是由W3C组织提出,最早由Netscape社区发展的一种机制。目前Cookie已经成为标准,所有的主流浏览器如IE、Netscape、Firefox、Opera等都支持Cookie。

由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。

Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。
查看某个网站颁发的Cookie很简单。在浏览器控制台输入document. Cookie,按回车就可以了,得到的是一个字符串。

cookie

注意:
1.Cookie功能需要浏览器的支持。
    如果浏览器不支持Cookie(如大部分手机中的浏览器)或者把Cookie禁用了,Cookie功能就会失效。

2.不同的浏览器采用不同的方式保存Cookie。
    IE浏览器会在“C:\Documents and Settings\你的用户名\Cookies”文件夹下以文本文件形式保存,一个文本文件保存一个Cookie。

3.Cookie的不可跨域名性

很多网站都会使用Cookie。例如,Google会向客户端颁发Cookie,Baidu也会向客户端颁发Cookie。那浏览器访问Google会不会也携带上Baidu颁发的Cookie呢?或者Google能不能修改Baidu颁发的Cookie呢?

答案是否定的。Cookie具有不可跨域名性。根据Cookie规范,浏览器访问Google只会携带Google的Cookie,而不会携带Baidu的Cookie。Google也只能操作Google的Cookie,而不能操作Baidu的Cookie。

Cookie在客户端是由浏览器来管理的。浏览器能够保证Google只会操作Google的Cookie而不会操作Baidu的Cookie,从而保证用户的隐私安全。浏览器判断一个网站是否能操作另一个网站Cookie的依据是域名。Google与Baidu的域名不一样,因此Google不能操作Baidu的Cookie。
需要注意的是,虽然网站images.google.com与网站www.google.com同属于Google,但是域名不一样,二者同样不能互相操作彼此的Cookie。

注意:用户登录网站www.google.com之后会发现访问images.google.com时登录信息仍然有效,而普通的Cookie是做不到的。这是因为Google做了特殊处理。

4.各浏览器对Cookie的限制

浏览器对Cookie 的限制主要体现在数量及大小上:

cookie的限制

超出个数限制后的处理操作:

1、IE与Opera的处理是一样的。他们都利用“最近最少使用算法”,当cookie已经达到限额时就将自动剔除最老的cookie,以给最新的cookie的留下可用的空间。

2、FF很特殊,虽然最后设置的cookie会被保留下来,但它好像没有什么章法随机进行删除已存在的cookie。

备注:
    在我们进行页面cookie操作的时候,应该尽量保证cookie的数量以及相应的大小。cookie个数最好 < 20~30个;cookie大小最好 < 4K

5.Cookie的所有属性

1、name:Cookie的名称,字符串类型。Cookie一旦创建,名称便不可更改。

2、value:Cookie的值,字符串类型。

3、Expires /maxAge:该Cookie失效的时间,单位秒。如果为正数,则该Cookie在maxAge秒之后失效。如果为负数,该Cookie为临时Cookie,关闭浏览器即失效,浏览器也不会以任何形式保存该Cookie。如果为0,表示删除该Cookie。默认为–1。只可写,不可读。

4、domain:可以访问该Cookie的域名,不可更改。如果设置为“.google.com”,则所有以“google.com”结尾的域名都可以访问该Cookie。注意第一个字符必须为“.”,默认值当前域名。

5、path:可以访问此cookie的页面路径。 比如domain是abc.com,path是/test,那么只有abc.com/test路径下的页面可以读取此cookie。path 只可写,不可读,不可更改。与 expires 不一样,如果我们试图更改 path,那么实际上我们是另外写了一个 cookie,而不是更改了 path 值。path 权限有继承性, 假如指定了 /test/ 目录有权限读取某 cookie,那么 /test/ 之下的目录 /test/t/ 也有权限读取该 cookie。默认值当前域名下的访问路径。

6、Size:此cookie大小。

7、http:cookie的httponly属性。若此属性为true,则只有在http请求头中会带有此cookie的信息,而不能通过document.cookie来访问此cookie。即通过js脚本将无法读取到cookie信息,这样能有效的防止XSS攻击。http属性只能通过后台语言来设置。

8、secure:设置是否只能通过https来传递此条cookie,默认false,设置为true,在http协议下无法访问。

9、SameSite:SameSite-cookies是一种机制,用于定义cookie如何跨域发送。这是谷歌开发的一种安全机制,并且现在在最新版本(Chrome Dev 51.0.2704.4)中已经开始实行了。SameSite-cookies的目的是尝试阻止CSRF(Cross-site request forgery 跨站请求伪造)以及XSSI(Cross Site Script Inclusion (XSSI) 跨站脚本包含)攻击。SameSite需要一个值,值可以是Lax或者Strict。

strict:严格模式,表明这个 cookie 在任何情况下都不可能作为第三方 cookie,绝无例外。有能力阻止所有CSRF攻击。然而,它的用户友好性太差。

Lax:宽松模式,比 Strict 放宽了点限制:假如这个请求是改变了当前页面或者打开了新页面且同时是个 GET 请求(因为从语义上说 GET 是读取操作,比 POST 更安全),则这个 cookie 可以作为第三方 cookie。建议使用Lax。

关于SameSite 这里讲的可能不是很详细,想了解的可以自行谷歌

6.JS操作Cookie的方法

注意:
同名的 cookie,不同的 domain 或不同的 path,属不同的 cookie; 

同名的 cookie,相同的 domain 且相同的 path,不同的 expires,属同一个 cookie。

1.读取cookie
document.cookie可以获取到该域名该路径下可获取到的所有的cookie的name和value的键值对(设置了HTTP属性为true获取不到,设置secure属性为true的在http协议下获取不到)。

cookie

Cookie是可以具有相同name,或者相同value的,所以我们获取的应该是一组值。

比如下面我们根据name检索所有的键值对:

function getCookie(name){
   var reg=new RegExp('(^| )'+name+'=([^;]*)(;|$)','g');
   return document.cookie.match(reg);
}
getCookie(‘hanfei2’);// [" hanfei2=24;", " hanfei2=24"]

2.设置cookies

function setCookie(option){
    option = option || {};
    //option 可设置属性:name value domain expires path secure SameSite
    if(option.expires){//将配置项中的过期时间格式化
        option.expires = +new Date() + option.expires*1000;
        option.expires = new Date(option.expires).toGMTString();
    }
    var cookie = [];
    for(var key in option){
        cookie.push(key + "=" + option[key])
    }
    document.cookie = cookie.join("; ")
}

setCookie({
    myCookie:'myCookieValue',//name-value
    expires:30*24*60*60,//过期时间,单位:秒
    // domain:'.baidu.com',//访问域名,一般不设置
    //path:'/',//可访问路径,权限域名下所有路径都可访问
    //secure:false,// 是否仅被使用安全协议传输
    //SameSite:'Lax'//请求限制
})

3.删除cookie
Cookie并不提供修改、删除操作。如果要修改某个Cookie,只需要新建一个同名的Cookie,覆盖原来的Cookie。

如果要删除某个Cookie,只需要新建一个同名的Cookie,并将expires/maxAge设置为0,并添加覆盖原来的Cookie。注意是0而不是负数。负数代表其他的意义。读者可以通过上例的程序进行验证,设置不同的属性。

注意:修改、删除Cookie时,新建的Cookie除value、expires/maxAge之外的所有属性,例如name、path、domain等,都要与原Cookie完全一样。否则,浏览器将视为两个不同的Cookie不予覆盖,导致修改、删除失败。

所以,要删除一个cookie,就是设置一个什么都相同,唯有过期时间为0的cookie:

setCookie({
    myCookie:'myCookieValue',//name-value
    expires:0,//过期时间,单位:秒
    // domain:'.baidu.com',//访问域名,一般不设置
    //path:'/',//可访问路径,权限域名下所有路径都可访问
    //secure:false,// 是否仅被使用安全协议传输
    //SameSite:'Lax'//请求限制
})

7.前端怎么传递cookie给后端?

以 Jquery 的 ajax 为例:

$.ajax({
    url : 'http://remote.domain.com/corsrequest',
    data : data,
    dataType: 'json',
    type : 'POST',
    xhrFields: {
        withCredentials: true
    },
    crossDomain: true,
    seccuss:function(data){
        console.log(data)
    },
    error:function(err){
        console.log(err)
    }
})

1、通过设置crossDomain: true , 发送Ajax时,Request header 中会包含跨域的额外信息,但不会含cookie。
2、通过设置 withCredentials: true ,发送Ajax时,Request header中便会带上 Cookie 信息。

猜你喜欢

转载自blog.csdn.net/hf872914334/article/details/78979007