天天看点

Cookie详解cookie

cookie

cookie

是浏览器端的一种数据存储,常和

localStorage

session

一起比较,常被用来记录用户的身份信息状态,为无状态的http请求添加了访问用户的身份标志。只要满足了发送条件,就会自动添加到

http请求头

中。满足条件是根据cookie的几个可选属性决定的,首先cookie是以键值对的方式存储(

name = value

),每个键值对还有不同的可选属性,都可以在设置cookie时一并添加:

  • path

    :可以访问cookie的页面路径,该路径及它的子路径都可以访问
  • domain

    :可以访问cookie的域名,该域名及它的子域名都可访问
  • max-age

    expire

    :都是设置cookie的存储周期,

    expire

    是一个绝对的过期时间,以客户端为准,

    max-age

    是一个相对存储时间。不设置超时时间的cookie存储周期为session,浏览器关闭后,cookie失效
  • secure

    :限制只能通过

    https

    发送cookie
  • httpOnly

    :限制只有http请求才能访问cookie,这样客户端脚本就不能读取cookie了,可以预防

    xss攻击

  • SameSite

    :最开始由Chrome浏览器提出,现在已经得到了很多浏览器的支持,主要是用来防止csrf攻击

这些属性决定了cookie什么时候、什么场景下被使用。

设置cookie的方式

设置cookie的方式有两种,客户端和服务端,客户端通过

document.cookie

设置,每次仅能对一个cookie进行设置和更新,可以参考MDN文档。服务端通过Set-Cookie响应头设置。需要注意的一点是cookie的

domain

的默认值是服务端或客户端当前的域名,即使设置,也只能是当前域名及其父域名。

跨域cookie

前面说了,只要满足上面的可选属性,cookie就会自动被发送,但是有一种情况例外。就是当跨域请求发生时,浏览器默认不会携带cookie,即便cookie满足

domain, path, secure

等属性。想要发送cookie需要分别在客户端和服务端进行相应的设置。

客户端需要添加携带cookie的标志:

1.ajax可以添加

withCredentials: true

的选项

2.fetch可以添加

credentials: 'include'

选项

服务端需要携带Access-Control-Allow-Credentials: true响应头,同时

Access-Control-Allow-Origin

响应头不能为:

*

通配符,只能指定具体的单一域名。

当然也可以使用代理来避免前后端跨域的问题。

SameSite属性

sameSite

属性在

Chrome 51

开始添加,在

Chrome 80

后将默认值设置为

Lax

,主要用来限制跨站点cookie的发送情况。注意,这里的跨站和跨域是两个不同的定义。同站表示两个域名的二级域名+顶级域名相同。且顶级域名得是

有效顶级域名(eTLD)

,有效顶级域名注册在

Mozilla

维护的公共后缀列表(Public Suffix List)中,例如

.com, .co.uk, pvt.k12.ma.us

。所以

a.baidu.com

b.baidu.com

是同站,

a.github.io

b.github.io

不是同站,因为

github.io

不属于有效顶级域名。

samesite

有三个值:

  • Strict

    完全禁止跨站cookie的传递
  • Lax

    大多数情况不发送跨站cookie,具体如下
请求类型 示例 正常情况 Lax
链接

<a href="..." target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" ></a>

发送 Cookie 发送 Cookie
预加载

<link rel="prerender" href="..." target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" />

发送 Cookie 发送 Cookie
GET 表单

<form method="GET" action="...">

发送 Cookie 发送 Cookie
POST 表单

<form method="POST" action="...">

发送 Cookie 不发送
iframe

<iframe src="..."></iframe>

发送 Cookie 不发送
AJAX

$.get("...")

发送 Cookie 不发送
Image

<img src="...">

发送 Cookie 不发送
  • None

    无论是否跨站都会发送cookie

csrf攻击

csrf全称是:

Cross-site request forgery

,意思为跨站点伪造攻击。原理是借助用户已有的身份标志,去完成攻击操作。例如用户在某系统登录成功后,进入到了另外的攻击网站,网站后台不经过用户允许发起删除数据、篡改数据的操作(

由于已经登录成功,会携带cookie身份标志

)。防御这类攻击的方案有多种:

1.阻止cookie身份标志在未经允许的情况下被发送,可以借助

samesite

属性实现

2.由于攻击请求都是来源于攻击网站,服务端可以通过

referer

头来验证请求方的身份

3.

csrftoken

,csrf攻击的要点就是用户身份可以伪造,所以我们可以在请求中加入一些自己的标志,由服务端为客户端生成专用的token,在发送请求时添加到请求头中,攻击网站发起的恶意攻击则不能伪造出这样的标志

和localStorage的比较

cookie

相比较,

localStorage

的优势是存储空间更大,而在安全性方面,反而不如

cookie

,对于xss攻击,

cookie

localStorage

都可以被读取,但

cookie

可以设置

httpOnly

属性,

localStorage

没有任何的防御机制。

和session的比较

session

是被存储在服务端的,也就是服务器的内存中,相对

cookie

,使用session存储重要信息更安全,但是也有缺点,会消耗服务器内存,同时session在多台服务器的同步也是一个问题。