什么是SameSite?
A request is “same-site” if its target’s URI’s origin’s registrable
domain is an exact match for the request’s client’s “site for
cookies”, or if the request has no client. The request is otherwise
“cross-site”.
For a given request (“request”), the following algorithm returns
“same-site” or “cross-site”:
- If “request”‘s client is “null”, return “same-site”.
Note that this is the case for navigation triggered by the user
directly (e.g. by typing directly into a user agent's address
bar).
- Let “site” be “request”‘s client’s “site for cookies” (as defined
in the following sections).
- Let “target” be the registrable domain of “request”‘s current
url.
- If “site” is an exact match for “target”, return “same-site”.
- Return “cross-site”.
The request’s client’s “site for cookies” is calculated depending
upon its client’s type, as described in the following subsections:
如上文所示,只有当请求的站点的 origin 和 当前浏览器站点地址origin 完全匹配时,才叫做 same-site,具体采用以下策略:
- request client 为null(如用户直接在浏览器中输入url),则为same-site
请求类型
文档请求(Document-based requests)
只有用户自己输入的URL才是暴露给用户的唯一安全的上下文。该URL对应的domain也应该是用户信任的站点。我们将其标记为 top-level-site。
因此,对于这样的请求,其 “site for cookies” 可以认为就是 top-level-site。
对于top-level-site中嵌套的上下文,只有当每一个文档及其祖先文档的origin与当前top-level-site相同时,site-for-cookies才等于top-level-site,否则则为空字符串。
Worker 请求
专用以及共享的worker
专用的worker都绑定了唯一的文档,因此这种类型的worker发出的请求(importScripts、XHR、fetch等)其site-for-cookies 就是绑定文档的site。
共享的worker可能一次性绑定了多个文档,这些文档的 “site-for-cookies”值可能都不一致,在这种情况下,最后会返回一个空字符串,当所有值都相同的时候,则返回相同的这个值。
简而言之,只要有一个文档的 document-site 和 worker 注册的site 不一致,那么就返回空字符串。
ServiceWorker
返回注册 worker 的 origin 的host
从 Chrome 51 开始,浏览器的 Cookie 新增加了一个SameSite属性,用来防止 CSRF 攻击和用户追踪。
**Set-Cookie: CookieName=CookieValue; SameSite=Strict;**
该属性有三个值:Strict、Lax、None
值
Strict
只有在第一方(宿主)上下文才会发送Cookie。第三方站点初始化的请求都不会携带Cookie。包含从宿主环境打开的链接 —— 如在a.b.com打开了,a.c.com的页面,那么在刚刚打开的这个页面中, SameSite 为 Strict 的 Cookie也不会被发送, 因为它是由B打开的。只有用户主动输入a.c.com的链接的情况下,SameSite 为 Strict 的Cookie才会被发送。
不确定是否是根据document.referrer判断的,因为该属性为只读属性
Lax
TOP-LEVEL NAVIGATIONS 下的请求允许发送Cookie;以及被第三方站点初始化的get请求(导航到目标网址的 Get 请求)也允许发送 Cookie;现代浏览器默认为它。
None
在所有的上下文当中 Cookie 都允许被发送,跨域也允许。
None 值在以前作为浏览器的默认值,但是在最近浏览器默认值变为了Lax,以防范CSRF攻击。
最新的浏览器要求在指定SameSite为None的同时,要求指定Secure属性;
备注
- Node 要发送多个相同名称的Header(如Set Cookie)的haul,需要使用
res.setHeader(headerName, valueArray)
的方式,并且如果后续调用writeHead的话,不能重复添加相应的Header
示例代码:
1 | const http = require('http') |
1 | const http = require('http') |
1 |
|
参考文档:
- SameSite