与Cookie有关的疑问

941 阅读5分钟

其实,在平时的项目当中,早就遇到过很多关于Cookie的疑惑,那就开始系统性的学习一下吧。

Cookie是什么?

简单来说,HTTP是一个无状态协议,有了Cookie HTTP请求可以携带少量状态。

HTTP协议是一个无状态协议,即它不会对发送的请求和响应状态进行保存,上一次请求和下一次请求是不是来自于同一个用户,它根本无法识别。但是,在项目当中,我们希望浏览器能够保持登录状态、记住购物车中的物品和数量等等,这就需要用到Cookie。

cookie就是一个浏览器管理状态的一个文件。浏览器会存储set-cookie字段里面的信息,并在该请求之后的所有请求,都携带cookie在其请求头中发送给服务器,服务器就可以读取到信息达到保持用户状态的作用。

Cookie原理

image.png

在看这张图的时候,一直有几个疑惑:

  • 我在项目当中如何区分第一次请求?
  • 为什么没有看到返回set-cookie的请求?

我们以登录状态为例,第一次请求其实对应的就是每一次的用户登录(login),我们打开登录的接口,可以看到,用户将自己的用户名、密码以请求参数的形式发送给服务端。登陆成功之后会在响应头中发现set-cookie这个字段,意为服务器将用户的登录态加密之后返回给客户端,会在cookie过期之前保存在浏览器缓存中。

以后的每一次请求,浏览器都会携带此Cookie来表明自己的身份。

屏幕快照 2021-06-15 上午10.03.57.png

屏幕快照 2021-06-11 上午11.33.56.png

Cookie的限制以及应用

屏幕快照 2021-06-11 上午11.33.56.png

在set-cookie的时候,会有一个domain的域名字段,表示该cookie只在访问该域名时会被携带(图中为.jd.com,意为访问jd.com下的所有二级域名都会被携带)。

用处:可以在一级域名下的所有子域名的网站共用一个登录态。

疑惑:一些cookie的expires(过期时间)为session,表示会话结束就删除cookie,为什么关掉浏览器还是会保存此cookie?

cookie的expires(过期时间)为session,表示在浏览器关闭之后就将cookie删除,但是chrome浏览器会默认保存cookie,需要设置“退出 Chrome 时清除 Cookie 及网站数据”,退出浏览器之后所有的cookie信息都会被删除。这个时候cookie的过期时间就跟浏览器会话过期时间有关。

Cookie的写入规则

问题描述:在 a.jd.com 网址控制台中写入一个Cookie: document.cookie='myname=zhangsan;path=/;domain=b.jd.com';

不生效!!只能向当前域、子域写cookie。

因为不管是js还是服务器设置Cookie,只能向当前域、更高级域写入Cookie。即a.jd.com只能向jd.coma.jd.com写入Cookie(只能操作自己域相关Cookie,别人的不能动)。

那关于b.jd.com的Cookie或者a.taobao.com的Cookie是怎么写入的呢?

通过向b.jd.com服务器发送请求,b.jd.com服务器就可以通过set-cookie字段设置有关于自己域名下b.jd.com的Cookie。(因为是在它的当前域)

注:application中不在当前域、更高域下的Cookie是看不到的(火狐),这是不同浏览器的实现方式不一样,但是其实都设置成功了,在浏览器的Cookie中都可以看到。

Cookie属性

屏幕快照 2021-04-27 上午10.02.25.png

打开控制台Application中的cookies,就可以看到各个cookie字段的属性。

Name

cookie的名字,同一个域名下的cookie的名字不能相同,不然会被覆盖掉。

Value

表示cookie的值,由于cookie规定是名称/值是不允许包含分号,逗号,空格的,所以为了不给用户到来麻烦,考虑服务器的兼容性,任何存储cookie的数据都应该被编码。

Domain

表示该cookie被绑定到某一个域名下,只要访问该域名,就会携带该cookie。 .baidu.com对于baidu.com的所有子域名都有效。但是相同一级域名下的不同二级域名之间是不能相互交换cookie的,比如domain为a.baidu.com下的cookie与domain为b.baidu.com下的cookie是不能共用的。

Path

对于指定域名下的某一个路径,发送该cookie,其他路径则不发送。 默认为‘/’,对于该域下的所有路径都使用该cookie。 可指定某一个cookie只有路径为 baidu.com/path/ 的时候才可发送。

Expires

该cookie的到期时间。默认情况下,cookie会在会话结束后就被删除,但是也可以设置成就算浏览器关闭也依然保存在浏览器内存中。

除了代码中设置的过期时间,cookie的保存还会收到浏览器自定义设置的影响。上文有提到。

Secure

在此字段为true时,表示该cookie只有在使用https访问的时候才会发送。

例:cookie只会发送给xxx.baidu.com 而不会发送给 xxx.baidu.com

HttpOnly

此字段设置为true时,表示该cookie不能通过js去获取(document.cookie),可以有效的防止xss(跨站脚本攻击)。

SameSite

这个属性是关于浏览器如何处理第三方cookie的,比如我们在跨站跳转链接时,是否可以携带第三方cookie? 由于之前在项目当中遇到过关于SameSite的问题,这里决定详细的说一下这个字段。

SameSite与第三方Cookie

Cookie缺点

  • 容量有限:Cookie 的体积上限只有4KB,只能用来存储少量的信息。
  • 性能缺陷:Cookie 紧跟域名,不管域名下面的某一个地址需不需要这个 Cookie ,请求都会携带上完整的 Cookie,这样随着请求数的增多,其实会造成巨大的性能浪费。
  • 安全缺陷:由于 Cookie 以纯文本的形式在浏览器和服务器中传递,很容易被非法用户截获,然后进行一系列的篡改,在 Cookie 的有效期内重新发送给服务器,这是相当危险的。另外,在HttpOnly为 false 的情况下,Cookie 信息能直接通过 JS 脚本来读取。