浏览器同源策略问题 - Cookie访问限制

简介: 对应cookie来说,浏览器的同源策略将会限制不同源间的访问,对于跨站和跨域来说对访问cookie的影响也是不同的。同站请求,对于使用HTTPS协议的API,浏览器会存储cookie,不论`samesite`的值;对于使用HTTP协议的API,浏览器会存储`samesite`的值为`Lax`和`Strict`的cookie。跨站请求,对于HTTPS协议的API返回的cookie,如果设置了属性:`secure; samesite=none`,则浏览器会存储cookie,XHR请求也会带上目标域的cookie。

1. 跨站(cross-site)、跨域(cross-origin)

以下两个域名就属于跨站,他们具有不同的二级域名pro.comdev.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.withCredentials

XMLHttpRequest.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.withCredentialstrue还是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的值为LaxStrict的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的值为LaxStrict的cookie;

    XHR请求会带上目标域的cookie;

  • cross-site

    对于HTTPS协议的API返回的cookie,如果设置了属性:secure; samesite=none,则浏览器会存储cookie。XHR请求也会带上目标域的cookie。

跨站一定跨域。

相关实践学习
基于函数计算快速搭建Hexo博客系统
本场景介绍如何使用阿里云函数计算服务命令行工具快速搭建一个Hexo博客。
目录
相关文章
|
5月前
|
Nacos
服务器部署 Nacos 获取不到配置浏览器可以访问
[Nacos Config] config[dataId=ruoyi-auth.yml,group=DEFAULT_GROUP] is empty、Nacos无法注册、gRPC、端口偏移
119 0
服务器部署 Nacos 获取不到配置浏览器可以访问
|
7月前
|
存储 搜索推荐 数据挖掘
使用selenium库模拟浏览器行为,获取网页的cookie值
使用selenium库模拟浏览器行为,获取网页的cookie值
|
6月前
|
JavaScript 对象存储
在阿里云OpenAPI 为什么oss 图片链接, 在浏览器访问直接下载了,不是预览呢?
在阿里云OpenAPI 为什么oss 图片链接, 在浏览器访问直接下载了,不是预览呢?
434 1
|
10天前
|
Ubuntu 关系型数据库 MySQL
如何在Ubuntu使用宝塔部署Emlog网站并发布到公网实现任意浏览器访问
如何在Ubuntu使用宝塔部署Emlog网站并发布到公网实现任意浏览器访问
|
10天前
|
JavaScript 前端开发 安全
JavaScript DOM 操作:解释一下浏览器的同源策略。
**同源策略**是浏览器安全基石,它阻止脚本跨不同协议、域名或端口访问资源,防止恶意行为。例如,HTTP页面无法直接用JS获取HTTPS页面内容。**CORS**允许跨域请求,但需服务器配合设置,通过`document.domain`属性可配置,但仍受限于服务器配置。
14 4
|
2月前
|
域名解析 应用服务中间件 对象存储
解决阿里云oss图片浏览器访问直接下载而不是打开
解决阿里云oss图片浏览器访问直接下载而不是打开
354 0
|
2月前
|
缓存 网络协议 前端开发
浏览器访问缓存都发生了什么
浏览器访问缓存都发生了什么
|
3月前
|
数据采集 安全 Go
一文看懂 如何操作浏览器访问网页
一文看懂 如何操作浏览器访问网页
33 0
|
3月前
|
JavaScript 前端开发 Go
浏览器中的同源策略
【1月更文挑战第2天】
|
4月前
|
Web App开发 Linux Windows
linux安装浏览器 linux本地浏览器进行访问
linux安装浏览器 linux本地浏览器进行访问