cookie完全教程

November 29, 20207分钟阅读

cookie 是后端可以存储在用户浏览器中的微小数据块。用户跟踪、个性化以及最重要的身份验证是 cookies 最常见的用例。

Cookie 有很多隐私问题,多年来一直受到严格的监管

在这篇文章中,我将主要关注技术方面:您将学习如何在前端和后端创建、使用和使用 http cookie。

配置后端服务

使用 express 搭建简易后端服务

git clone -b basic-server https://github.com/JennerChen/cookie-guide.git

cd basic-server && yarn

yarn run server

你将会启动一个 web 服务,通过访问 localhost:3000 会看到页面内容如下

1606631217565 9D9DB3B0 687D 41A6 8387 47D8C4547619

服务端和客户端都可以设置 cookie, 客户端在设置 cookie 时有一些限制。通常来说,在服务端设置的 cookie 用于用户私密状态保存

服务端设置

通过响应头Set-Cookie设置 cookie, 如下代码第 8 行res.set('Set-Cookie', 'mycookie=beaf')会以 key/value 形式设置 mycookie=beaf

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  const content = `
        <h2>basic set cookie</h2>
        <p>cookie demo</p>
    `
  res.set('Set-Cookie', 'mycookie=beaf')  res.send(content)
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

1606631586567 05433784 14BD 4181 AF90 171CAB78F87F

查看本片段代码 https://github.com/JennerChen/cookie-guide/tree/server-set-cookie

查看 cookie:

  • 通过 document.cookie 查看

1606631439825 1EE02620 F7A6 4F4F 9000 50509F13452B

若不想客户端通过 document.cookie 获取该字段, 可以额外添加HttpOnly(res.set(‘Set-Cookie’, ‘mycookie=beaf;HttpOnly’))

1606632297889 95EFE248 DF56 4042 9968 66C6BEFEBF3D

  • 通过 chrome devtool 查看

1606631487296 080CF31A E45D 4182 9AA6 2410CEE7ECBF

  • 命令行
curl -I http://127.0.0.1:3000 --cookie-jar mycookie

path 和 domain

path用于设置 cookie 在同一个域名下的可见范围,domain用于不同域名之间 cookie 的隔离。

如下例子, cookie scopeValueA只能在 /pathA 路径下获取, scopeValueB只能在 /pathB 路径下获取

app.get('/pathA', (req, res) => {
  const content = `
        <h2>set only pathA</h2>
        <h2>you only can see scopeValue in /pathA</h2>
    `
  res.set('Set-Cookie', 'scopeValueA=pathA;path=/pathA')  res.send(content)
})

app.get('/pathB', (req, res) => {
  const content = `
        <h2>set only pathA</h2>
        <h2>you only can see scopeValue in /pathB</h2>
    `
  res.set('Set-Cookie', 'scopeValueB=pathB;path=/pathB')  res.send(content)
})

1607237468731 059A8427 1124 47FF 8ADB 2F4F18E8D604

和 path 类似,但 domain 只允许设置当前 host, 不允许设置其他域名

app.get('/set-domain-taobao', (req, res) => {
  const content = `
        <h2>don't allow set other domain</h2>
        <h2>you only can set current domain</h2>
    `
  res.set('Set-Cookie', 'otherDomainCookie=beaf;domain=*.taobao.com')  res.send(content)
})

在 chrome 下, 会得到一个警告, 所以浏览器会拒绝设置。 1607237719630 105E0A97 22C3 4AA4 8212 E375CC0CB907 1

域名支持 wildcard 配置,简单来说 example.com 能够配置 所有 *.example.com 下的 cookie。 详见域名匹配规则

异步 ajax 请求

ajax 可以携带/设置 cookie

app.get('/ajax-cookie', (req, res) => {
  let cookieValue = Math.random()
  const content = `
       you were setting cookie ajaxCookie with value ${cookieValue}
    `
  res.set('Set-Cookie', `ajaxCookie=${cookieValue}`)
  res.send(content)
})

在浏览器中, 执行如下代码

fetch('/ajax-cookie')
  .then(data => data.text())
  .then(console.log)

1607239012876 8F152AFE 3001 4762 B978 14B0CBCD5CF7

若请求为跨域请求(localhost:3000 请求 localhost:3001), 服务端必须配置cors且客户端需要声明 credentials: “include”才能携带 cookie

https 访问: Secure

name

名称, cookie 以 key/value 存储, key 即 name

value

cookie 名称对应的值, 可以以任意字符串保存(json 务必以 JSON.stringify 方式保存)

expire/Max-Age

cookie 有效期, 默认为 Session, 即关闭浏览器即过期。

Max-Age 优先级高于 expire

Max-Age 指客户端创建 cookie, 有效的时间段。 expire 是具体日期如 2020-12-31, 即 2020-12-31 过期

path

path 指 cookie 的范围. 例如 res.set('Set-Cookie', 'scopeValueA=pathA;path=/pathA'),那么 scopeValue 仅可在 pathA 下获取。详见例子

当不传 path, path 默认值为/, 即全部可见

domain

domain 是 cookie 的分割范围,仅能设置当前域名。配置方式和 path 类似

httpOnly

是否允许客户端读取字段,默认 false。 若配置为 true, 那么 document.cookie 无法获取。

Secure

是否仅允许 https 协议访问, 若配置成 true, cookie 必须在 https 协议下生效

该值仅可在服务端设置

sameSite

共有 3 种有效值,先期默认值为None, 先阶段默认值为Lax

  • Lax: 所有的 cookie 只能在first-party端中使用,在third-party会被拦截。 但third-party链接会携带 cookie
  • Strict 所有的 cookie 只能在first-party端中使用,在third-party会被拦截, 包括third-party链接
  • None cookie 都能在first-party,third-party中使用,但必须开启 secure 标签

first-party 为 _.example.com 的域名。 所有不满足 _.example.com 的域名称为 third-party

若期望 cookie 被 third-party 携带, 必须启用 secure, 例如 Set-Cookie: flavor=choco; SameSite=None; Secure 。 换句话说,必须使用 https 才能搭配 samesite=none 使用

Priority

优先级, 当 cookie 超出容积时,基于如下顺序删除 cookie low->medium->high.默认为 medium, 故常用做法是将 用户 token 存于 high, 用户行为信息存于 low

  • high:
  • medium
  • low

Reference

未经许可, 不可转载