对应cookie来说 浏览器的同源策略将会限制不同源间的访问 对于跨站和跨域来说对访问cookie的影响也是不同的。同站请求 对于使用HTTPS协议的API 浏览器会存储cookie 不论samesite的值 对于使用HTTP协议的API 浏览器会存储samesite的值为Lax和Strict的cookie。跨站请求 对于HTTPS协议的API返回的cookie 如果设置了属性 secure; samesite none 则浏览器会存储cookie XHR请求也会带上目标域的cookie。对于HTTP协议的API不能存储cookie 在浏览器开发者工具 网络面板中可以看到set-cookie后有告警图标 鼠标放上后可以看到相关说明。
1. 跨站(cross-site)、跨域 cross-origin以下两个域名就属于跨站 他们具有不同的二级域名pro.com和 dev.com。
ocs.pro.com
ocs.dev.com
以下两个域名就属于同站 具有相同的域名test.com。
ocs.test.com
sts.test.com
2. cookie 的 SameSite 属性Chrome 51 开始 浏览器的 cookie 新增加了一个SameSite属性 用来防止 CSRF 攻击和用户追踪。
cookie 的 SameSite属性是用于设置cookie的访问范围的
它可以设置三个值。
Strict
Strict最为严格 完全禁止第三方 cookie 跨站点时 任何情况下都不会发送 cookie。换言之 只有当前网页的 URL 与请求目标一致 才会带上 cookie。
Set-cookie: cookieName cookievalue; SameSite Lax;
这个规则过于严格 可能造成非常不好的用户体验。比如 当前网页有一个 GitHub 链接 用户点击跳转就不会带有 GitHub 的 cookie 跳转过去总是未登陆状态。
Lax Lax规则稍稍放宽 大多数情况也是不发送第三方 cookie 但是导航到目标网址的 Get 请求除外。
Set-cookie: cookieName cookievalue; SameSite Lax;
设置了Strict或Lax以后 基本就杜绝了 CSRF 攻击。当然 前提是用户浏览器支持 SameSite 属性。
None
Chrome 计划将Lax变为默认设置。这时 网站可以选择显式关闭SameSite属性 将其设为None。不过 前提是必须同时设置Secure属性 cookie 只能通过 HTTPS 协议发送 否则无效。 下面的设置无效。
Set-cookie: widget_session abc123; SameSite None
下面的设置有效
Set-cookie: widget_session abc123; SameSite None; Secure
3. XMLHttpRequest.withCredentialsXMLHttpRequest.withCredentials属性是一个布尔值 表示跨域请求时 用户信息 比如 cookie 和认证的 HTTP 头信息 是否会包含在请求之中 默认为false 即向 example.com 发出跨域请求时 不会发送 example.com 设置在本机上的 cookie 如果有的话 。
如果需要跨域 AJAX 请求发送 cookie 需要withCredentials属性设为true。注意 同源的请求不需要设置这个属性。
var xhr new XMLHttpRequest(); xhr.open( GET , http://ocs.test.com/ , true); xhr.withCredentials true; xhr.send(null);
为了让这个属性生效 服务器必须显式返回Access-Control-Allow-Credentials这个头信息。
Access-Control-Allow-Credentials: true withCredentials属性打开的话 跨域请求不仅会发送 cookie 还会设置远程主机指定的 cookie。反之也成立 如果withCredentials属性没有打开 那么跨域的 AJAX 请求即使明确要求浏览器设置 cookie 浏览器也会忽略。
注意 脚本总是遵守同源政策 无法从document.cookie或者 HTTP 回应的头信息之中 读取跨域的 cookie withCredentials属性不影响这一点。
4. cookie的访问同源 same-origin
无限制 无论XMLHttpRequest.withCredentials是true还是false 浏览器均可存储cookie XHR请求中均会带上cookie。
顶级导航 top-level navigation 即浏览器地址栏中直接输入地址 浏览器会存储cookie 不论cookie的samesite的值是多少。
XMLHttpRequest.withCredentials false cross-origin 同站 same-site
这种场景下 cookie不会被浏览器存储。
XMLHttpRequest.withCredentials false cross-origin 跨站 cross-site
这种场景下 cookie不会被浏览器存储。
XMLHttpRequest.withCredentials true cross-origin 跨站 cross-site
对于使用HTTP协议的API返回的cookie 浏览器不会存储 在浏览器开发者工具 网络面板中可以看到set-cookie后有告警图标 鼠标放上后可以看到相关说明。
对于HTTPS协议的API返回的cookie 如果设置了属性 secure; samesite none 则浏览器会存储cookie。XHR请求也会带上目标域的cookie。
XMLHttpRequest.withCredentials true cross-origin 同站 same-site
对于使用HTTPS协议的API 浏览器会存储cookie 不论samesite的值
对于使用HTTP协议的API 浏览器会存储samesite的值为Lax和Strict的cookie
XHR请求会带上目标域的cookie
// Java 设置secure; samesite none 方法
RestController
RequestMapping
public class TestController {
GetMapping( /test )
public Object test (HttpServletRequest request,
HttpServletResponse response) throws Exception {
Responsecookie cookie Responsecookie.from( mycookie , mycookievalue ) // key value
.httponly(true) // 禁止js读取
.secure(true) // 在http下也传输
.domain( localhost )// 域名
.path( / ) // path
.maxAge(Duration.ofHours(1)) // 1个小时候过期
.sameSite( None ) // 大多数情况也是不发送第三方 cookie 但是导航到目标网址的 Get 请求除外
.build()
// 设置cookie Header 使用andHeader能设置多个 setHeader只能设置一个SET_cookie
response.addHeader(HttpHeaders.SET_cookie, cookie.toString());
return ok
5 总结
同源时cookie的存储与发送没有问题,顶级导航的情况可以看作是同源场景
不同源场景 若XMLHttpRequest.withCredentials false 则浏览器不会存储cookie
不同源场景 且XMLHttpRequest.withCredentials true 又可分为以下场景
same-site
对于使用HTTPS协议的API 浏览器会存储cookie 不论samesite的值
对于使用HTTP协议的API 浏览器会存储samesite的值为Lax和Strict的cookie
XHR请求会带上目标域的cookie
cross-site
对于HTTPS协议的API返回的cookie 如果设置了属性 secure; samesite none 则浏览器会存储cookie。XHR请求也会带上目标域的cookie。
跨站一定跨域。



