![392fdf68bf760120132e651771de9bdf.png](https://i-blog.csdnimg.cn/blog_migrate/c5e62c574f916d4a87df644e65585ccd.jpeg)
title: Cookie实用原理总结 date: 2019-09-10 21:47:56 categories: - 技术 - 原理 tags: - Web前端 - Cookie - 小技巧
前言
此篇文章需要你掌握有关 Javascript | Web | HTTP 的基础知识。阅读时长约为5分钟。
其实作为一名现代的前端开发者,Cookie
的这个概念几乎不用接触,这个是上个时代遗留下来的东西,了解它不乏有点困惑。但新的技术总是会与老技术相互碰撞,可能让后端自行带上 Token
等一些信息,Cookie
是一种最方便的方法了。所以本篇文章,我们就来讲讲 Cookie
有哪些有用的地方,与其他值得注意使用的地方。
一、Cookie 的出现
Cookie
的用途主要是用来解决 HTTP
无状态的问题,我们都知道 HTTP
是没有状态的,也就是说我们每次的请求其实都是无状态的,如果不是 Javascript
可以主动设置请求头等信息的话,服务器是基本无法知道你是谁的。所以一般 Cookie
结合服务端的Session
会话功能,可以在你浏览并登陆之后,直到你退出页面都知道你是谁,你的商品到底加入到了谁的购物车。
除了提供可持续的状态,Cookie
还可以支持你的离线后再次记住你的功能。因为 Cookie
是可以设置过期时间(但不能永久,主动的清除缓存也会失效)。可是这样看起来 Cookie
是不是过于强大了呢?所以其实不好好用 Cookie
可能会造成一些人的滥用,从而导致用户的信息被盗等问题。
二、Cookie 到底怎么用?
document.cookie = "yummy_cookie=choco;domain=.icanvip.net";
其实这一句代码就可以用了,虽然不怎么好用看起来,但是它包含了 Cookie
的读取与设置,所以非常好上手。
以下可选的cookie
属性值可以跟在键值对后,用来具体化对cookie
的设定/更新,使用分号以作分隔:
- ;path=path (例如 '/', '/mydir') 如果没有定义,默认为当前文档位置的路径。
- ;domain=domain (例如 'example.com', 'subdomain.example.com') 如果没有定义,默认为当前文档位置的路径的域名部分。与早期规范相反的是,在域名前面加 . 符将会被忽视,因为浏览器也许会拒绝设置这样的cookie。如果指定了一个域,那么子域也包含在内。
- ;max-age=max-age-in-seconds (例如一年为60 * 60 * 24 *365)
- ;expires=date-in-GMTString-format 如果没有定义,cookie会在对话结束时过期 这个值的格式参见Date.toUTCString()
- ;secure (cookie只通过https协议传输)
cookie的值字符串可以用encodeURIComponent()来保证它不包含任何逗号、分号或空格(cookie值中禁止使用这些值).
上面也是摘自 https://developer.mozilla.org/zh-CN/docs/Web/API/Document/cookie
说的也是十分清楚,cookie 有哪些值可以设置。
三、Cookie 中的Q&A
1. 能设置或读取子域的 cookie
吗?
不行! 只能向当前域或者更高级域设置 cookie
例如 client.com
不能向 a.client.com
设置 cookie
, 而 a.client.com
可以向 client.com 设置 cookie
读取 cookie
情况同上
所以,如果你想在多个子域名下共享用户状态的话,可以利用这个原理进行对根域名的 Cookie 设置,这样其他子域名包含根域名的网址都可以读取到这个用户的状态。
2. 客户端设置 cookie
与服务端设置 cookie
有什么区别?
无论是客户端还是服务端, 都只能向自己的域或者更高级域设置 cookie
例如 client.com
不能向 server.com
设置 cookie
, 同样 server.com
也不能向 client.com
设置 cookie
服务端可以设置 httpOnly: true
, 带有该属性的cookie客户端无法读取 客户端只会带上与请求同域的 cookie
, 例如 client.com/index.html
会带上 client.com
的 cookie
, server.com/app.js
会带上 server.com
的 cookie
, 并且也会带上 httpOnly
的cookie
但是, 如果是向服务端的 ajax
请求, 则不会带上 cookie
, 详情见第三个问题
3. 同域/跨域ajax
请求到底会不会带上 cookie
?
这个问题与你发起 ajax
请求的方式有关 fetch
在默认情况下, 不管是同域还是跨域 ajax
请求都不会带上 cookie
, 只有当设置了 credentials
时才会带上该 ajax
请求所在域的 cookie
, 服务端需要设置响应头 Access-Control-Allow-Credentials: true
, 否则浏览器会因为安全限制而报错, 拿不到响应
fetch(url, {
credentials: "include", // include, same-origin, omit
})
axios
和 jQuery
在同域 ajax
请求时会带上 cookie
, 跨域请求不会, 跨域请求需要设置 withCredentials
和服务端响应头
js axios.get('http://server.com', {withCredentials: true})
```js $.ajax({ method: 'get', url: 'http://server.com', xhrFields: { withCredentials: true } })
以上原答案来自
> 作者:碎碎酱
链接:https://juejin.im/post/5b5df0aee51d451998415485
来源:掘金
# 四、最新的 Cookie 安全保证 --- Cookie 的 SameSite 属性
Cookie 的SameSite属性用来限制第三方 Cookie,从而减少安全风险。
它可以设置三个值。
- Strict
- Lax
- None
## 1. Strict
`Strict` 最为严格,完全禁止第三方 `Cookie`,跨站点时,任何情况下都不会发送 `Cookie`。换言之,只有当前网页的 `URL` 与请求目标一致,才会带上 `Cookie`。
Set-Cookie: CookieName=CookieValue; SameSite=Strict;
这个规则过于严格,可能造成非常不好的用户体验。比如,当前网页有一个 `GitHub` 链接,用户点击跳转就不会带有 `GitHub` 的 `Cookie`,跳转过去总是未登陆状态。
## 2. Lax
`Lax` 规则稍稍放宽,大多数情况也是不发送第三方 `Cookie`,但是导航到目标网址的 Get 请求除外。
Set-Cookie: CookieName=CookieValue; SameSite=Lax;
导航到目标网址的 `GET` 请求,只包括三种情况:链接,预加载请求,`GET` 表单。详见下表。
http://www.ruanyifeng.com/blog/2019/09/cookie-samesite.html
设置了 `Strict` 或 `Lax` 以后,基本就杜绝了 `CSRF` 攻击。当然,前提是用户浏览器支持 `SameSite` 属性。
## 3. None
`Chrome` 计划将Lax变为默认设置。这时,网站可以选择显式关闭 `SameSite` 属性,将其设为 `None` 。不过,前提是必须同时设置 `Secure` 属性( `Cookie` 只能通过 `HTTPS` 协议发送),否则无效。
下面的设置无效。
Set-Cookie: widget_session=abc123; SameSite=None
下面的设置有效。
Set-Cookie: widget_session=abc123; SameSite=None; Secure ```