一、Cookie介绍
因为 HTTP 是无状态的协议,它对于事务处理没有记忆能力,每个请求都是完全独立的、服务端无法分辨上一次的请求发送者和这一次的请求发送者是不是同一个人。
所以服务端和客户端为了进行会话追踪,需要维护一个状态来告知服务端前后两个请求是否来自同一浏览器,这个状态可以通过cookie或session实现。
1. cookie是什么
-
cookie 存储在客户端:
cookie是服务器发送到浏览器并保存在本地的一块数据,用于会话追踪。当浏览器下次向同一服务器发起请求时会携带该cookie。大小不超过 4KB,以键值对的形式存储数据。 -
cookie 是不能跨域的:每个
cookie都会绑定唯一域名,无法在别的域名下获取使用,向同一域名发送请求时都会携带相同的cookie。 -
怎么写cookie:服务端可以通过响应头中的
Set-Cookie字段来向客户端写入cookie。
// 请求头
Cookie: a=xxx;b=xxx
// 响应头
Set-Cookie: a=xxx
Set-Cookie: b=xxx
2. cookie 的重要属性
2.1 键值对:name, value
cookie的名称和对应值,必须为字符串类型。
同一个域名下绑定的cookie,name不能相同,否则会覆盖。
2.2 有效期:Expires,Max-Age
「cookie 过期后就会被删除,并不会发送给服务端」
- Expires:过期时间,
GMT格式。 - Max-Age:从浏览器收到报文开始计算,
cookie存在的秒数。优先级高于Expires。 - 如果没有指定,那么 cookie 默认只在当前会话(session)有效,浏览器窗口一旦关闭,cookie就不再保留。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
2.3 作用域:Domain,Path
指定可访问该cookie的域名和路径(默认'/')。
如果发现域名或路径和目标服务器不匹配,那么发请求时就不会携带该cookie。
2.4 安全相关:Secure,HttpOnly,SameSite
-
Secure:该 cookie 是否只能使用安全协议(
https、ssl等)传输,默认 false。true 则表示 cookie 只能通过 https 传输。 -
HttpOnly:设为
true则表示该cookie无法通过js脚本访问(如document.cookie),这也是防止XSS攻击的手段。 -
SameSite:用来防止
CSRF攻击,默认值现已改为Lax。可设置三个值,Strict:浏览器完全禁止第三方请求携带cookie,只能同站请求携带。(比如请求baidu.com网站时,域名只能是baidu.com的请求才能携带cookie,在其他网站请求都不能)Lax:规则放宽,大多数情况下第三方请求也不能携带 cookie,但导航到目标网址的Get请求除外。None:无论是否跨站都会携带cookie。设置为 None 时必须同时设置Secure属性,也就是说此时cookie只支持https协议传输。
SameSite的跨站:同站指的是顶级域名和二级域名相等即可,和同源不一样。
www.百度.com
主机名.二级域名.顶级域名
3. 应用场景
cookie常见的应用场景:
- 会话状态管理:保存用户登录状态、购物车(当你添加商品到购物车时,服务端不知道是哪个用户操作的)等需要记录的信息。
- 个性化设置:保存用户的偏好,如用户自定义设置、主题等。
二、cookie与http协议
cookie 由 http 协议生成,也主要是供 http 协议使用。
2.1 http响应:cookie的生成
服务器如果希望在浏览器中保存 Cookie,就要在 HTTP 响应的头信息里面,放置一个Set-Cookie字段,http 响应里可以包含多个Set-Cookie字段。
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly
2.2 http请求:cookie的发送
浏览器向服务器发送 http 请求时,每个请求都会带上相应的 cookie,使用 http 头信息的 cookie 字段。
Cookie: name=value; name2=value2; name3=value3
三、前端安全
1. csrf 攻击:跨站请求伪造
恶意网站伪造了带有正确 cookie 的 http 请求。 需要登录受信任网站,并在本地生成cookie。
例如,用户登录www.weibo.com,微博的服务器会发送1个cookie,用户后来又访问了恶意网站,网站中有www.weibo.com/api(子作用域)链接,那么当用户点击该连接时,微博服务器就会收到带有正确cookie的请求(第三方cookie),服务器就会认为是本人在操作,从而导致账号被劫持。
解决方法:
- 在 cookie 中设置 SameSite:lax 即可。
- 验证 token:服务器除了返回 cookie,还会返回一个token。之后服务器通过验证这个 token 来确认是否为安全的请求。
- 验证 http 的 Referer 字段:判断该url是否可信任。
2. xss 攻击:跨站脚本攻击
注入恶意脚本到网页中,当用户浏览该页面时,就会执行这些脚本,从而实现恶意攻击。
-
存储型 (持久):恶意代码存储在目标服务器上,当浏览器发送请求时,该恶意代码会随响应报文传回并解析执行。【与反射型的区别在于提交代码是否会存储在服务端】
场景:用户评论区,提交包含一条恶意代码的评论到数据库,其他用户看到该评论时,恶意代码会随响应报文返回,浏览器解析xss代码。
-
反射型 (非持久):恶意代码出现在 url中,当发请求时会作为输入提交到服务端,然后该恶意代码随响应报文一起传给浏览器,最后浏览器会解析执行该恶意代码。
-
DOM型:不经过服务端,通过修改dom节点,把恶意代码插入到了页面。【与后两者的区别在于不经过服务端】
注意:DOM型属于 js 自身的安全漏洞,前两种属于服务端的安全漏洞。
解决方法:
- HttpOnly:许多xss攻击目标是为了窃取用户cookie,设置 httpOnly 可以防止 JS 脚本获取cookie。
- 输入过滤检查:对输入内容进行转义或过滤,过滤掉那些会导致脚本执行的内容,用编码的方式替换
<script>等标签。