cookie
cookie
是浏览器端的一种数据存储,常和
localStorage
、
session
一起比较,常被用来记录用户的身份信息状态,为无状态的http请求添加了访问用户的身份标志。只要满足了发送条件,就会自动添加到
http请求头
中。满足条件是根据cookie的几个可选属性决定的,首先cookie是以键值对的方式存储(
name = value
),每个键值对还有不同的可选属性,都可以在设置cookie时一并添加:
-
:可以访问cookie的页面路径,该路径及它的子路径都可以访问path
-
:可以访问cookie的域名,该域名及它的子域名都可访问domain
-
和max-age
:都是设置cookie的存储周期,expire
是一个绝对的过期时间,以客户端为准,expire
是一个相对存储时间。不设置超时时间的cookie存储周期为session,浏览器关闭后,cookie失效max-age
-
:限制只能通过secure
发送cookiehttps
-
:限制只有http请求才能访问cookie,这样客户端脚本就不能读取cookie了,可以预防httpOnly
xss攻击
-
:最开始由Chrome浏览器提出,现在已经得到了很多浏览器的支持,主要是用来防止csrf攻击SameSite
这些属性决定了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
有三个值:
-
完全禁止跨站cookie的传递Strict
-
大多数情况不发送跨站cookie,具体如下Lax
请求类型 | 示例 | 正常情况 | Lax |
---|---|---|---|
链接 | | 发送 Cookie | 发送 Cookie |
预加载 | | 发送 Cookie | 发送 Cookie |
GET 表单 | | 发送 Cookie | 发送 Cookie |
POST 表单 | | 发送 Cookie | 不发送 |
iframe | | 发送 Cookie | 不发送 |
AJAX | | 发送 Cookie | 不发送 |
Image | | 发送 Cookie | 不发送 |
-
无论是否跨站都会发送cookieNone
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在多台服务器的同步也是一个问题。