共计 3879 个字符,预计需要花费 10 分钟才能阅读完成。
一、Cookie 是什么?
HTTP Cookie(也叫 Web Cookie 或浏览器 Cookie)是服务器发送到用户浏览器并保留在本地的一小块数据,它会在浏览器下次向同一服务器再发动申请时被携带并发送到服务器上。应用场景:
- 会话状态治理(如用户登录状态、购物车、游戏分数或其它须要记录的信息)
- 个性化设置(如用户自定义设置、主题等)
- 浏览器行为跟踪(如跟踪剖析用户行为等)
二、Cookie 生成过程
1、生成 cookie
服务器生成了 cookie 数据 并设置为 Set-Cookie
属性,蕴含在 HTTP 协定的 Header 中,来通知浏览器保留这些数据(除非浏览器禁用了 Cookie)。
// 服务端发给浏览器的数据
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
2、存储 cookie 并回传
浏览器会在接下来的申请中,把存储的 cookie 数据,设置为 Cookie
属性,蕴含 HTTP 协定的 Header 中,连同申请一起发送给服务器(除非设置了不发送 cookie)。
// 浏览器发给服务器的数据
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
三、第一方 和 第三方 Cookie
- Cookie 中的域名 与 以后站点域名雷同,称为 第一方 cookie(first-party cookie);
- Cookie 中的域名 与 以后站点域名不同,称为 第三方 cookie(third-party cookie);
以后站点会应用一些其余站点资源(譬如图片、广告等),在申请第三方服务器获取这些资源时,也会返回 Set-Cookie
属性,让浏览器保留第三方的 cookie,这些 cookie 次要用于用户跟踪,流量剖析等。
四、cookie 的重要属性
1、Secure 和 HttpOnly
性能:限度拜访 Cookie 的形式。
- Secure:示意 cookie 只能用 https 加密的形式发送给申请站点;
- HttpOnly:JavaScript API 无法访问带有 HttpOnly 属性的 cookie(
Document.cookie
无奈读取 cookie)当 cookie 中的数据,只用于服务器时,能够设置此属性;可避免通过 JavaScript 拜访 cookie 值; - 这两个属性能够无效进攻 大部分 XSS 攻打。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
2、Domain 和 Path
性能:容许 Cookie 发送给哪些 URL?
- Domain:示意 cookie 能够发送给那个域名包含其子域名。如果不设置 Domain,就取值为 origin 但不蕴含 origin 的子域名。如果设置
Domain=mozilla.org
,那么 cookie 也能发送给子域名developer.mozilla.org
。 - Path:示意 cookie 能够发送给那些门路。如果 设置
Path=/docs
,那么 cookie 也能发送给子门路/docs/Web/
。
3、SameSite
性能:能够限度 cookie 的跨域发送,此属性可无效避免大部分 CSRF 攻打,有三个值能够设置:
-
None:同站、跨站申请都发送 cookie,但须要 Secure 属性配合一起应用。
Set-Cookie: flavor=choco; SameSite=None; Secure
-
Strict:以后页面与跳转页面是雷同站点时,发送 cookie;
Set-Cookie: key=value; SameSite=Strict
- Lax:与 Strict 相似,但用户从内部站点导航至 URL 时(例如通过链接)除外。在新版本浏览器中,为默认选项,Same-site cookies 将会为一些跨站子申请保留,如图片加载或者 frames 的调用,但只有当用户从内部站点导航到 URL 时才会发送。如 link 链接
4、__Host-
和 __Secure-
能够创立 cookie 的中央很多,很难判断 cookie 的起源,然而可应用 cookie 前缀来断言 cookie 的起源。
-
__Host-
带有这个前缀的 cookie,必须具备这三个个性:有 Secure 属性、没有 Domain 属性、Path 值为 /,此类 cookie 被称之为
domain-locked
。 -
__Secure-
带有这个前缀的 cookie,示意必须具备 Secure 属性。
因为应用服务器仅在确定用户是否已通过身份验证或 CSRF 令牌正确时才查看特定的 cookie 名称,因而,这无效地充当了针对会话劫持的进攻措施。
五、操作 Cookie 的办法
1、JavaScript API
JavaScript 代码中通过 Document.cookie 来创立 Cookie,也能用其拜访不带 HttpOnly 标记的 Cookie。
document.cookie = "yummy_cookie=choco";
document.cookie = "tasty_cookie=strawberry";
console.log(document.cookie);
// logs "yummy_cookie=choco; tasty_cookie=strawberry"
2、cookie 库
Node.js 我的项目用 http 创立的 Web 服务,能够用 cookie 库
操作 cookie,实例如下:
var cookie = require('cookie');
var escapeHtml = require('escape-html');
var http = require('http');
var url = require('url');
function onRequest(req, res) {
// Parse the query string
var query = url.parse(req.url, true, true).query;
if (query && query.name) {
// Set a new cookie with the name
res.setHeader('Set-Cookie', cookie.serialize('name', String(query.name), {
httpOnly: true,
maxAge: 60 * 60 * 24 * 7 // 1 week
}));
// Redirect back after setting cookie
res.statusCode = 302;
res.setHeader('Location', req.headers.referer || '/');
res.end();
return;
}
// Parse the cookies on the request
var cookies = cookie.parse(req.headers.cookie || '');
// Get the visitor name set in the cookie
var name = cookies.name;
res.setHeader('Content-Type', 'text/html; charset=UTF-8');
if (name) {res.write('<p>Welcome back, <b>' + escapeHtml(name) + '</b>!</p>');
} else {res.write('<p>Hello, new visitor!</p>');
}
res.write('<form method="GET">');
res.write('<input placeholder="enter your name"name="name"> <input type="submit"value="Set Name">');
res.end('</form>');
}
http.createServer(onRequest).listen(3000);
- cookie – npm
- cookie – github
3、cookie-parser 库
express
我的项目 中应用 cookie-parser
来操作 cookie,实例如下:
var express = require('express')
var cookieParser = require('cookie-parser')
var app = express()
app.use(cookieParser())
app.get('/', function (req, res) {
// Cookies that have not been signed
console.log('Cookies:', req.cookies)
// Cookies that have been signed
console.log('Signed Cookies:', req.signedCookies)
})
app.listen(8080)
// curl command that sends an HTTP request with two cookies
// curl http://127.0.0.1:8080 --cookie "Cho=Kim;Greet=Hello"
- cookie-parser – npm
- cookie-parser – github
六、大量数据存储问题
大量服务端数据存储于 Cookie,升高了网络拜访性能(特地是挪动环境下),可通过 Web Storage API
和 IndexedDB
来解决。
- Web Storage API – MDN
- IndexedDB_API – MDN
七、参考文档
- 一篇解释分明 Cookie 是什么?