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

2023-02-18 00:00:00 策略 浏览器 同源

对应cookie来说,浏览器的同源策略将会限制不同源间的访问,对于跨站和跨域来说对访问cookie的影响也是不同的。同站请求,对于使用HTTPS协议的API,浏览器会存储cookie,不论samesite的值;对于使用HTTP协议的API,浏览器会存储samesite的值为LaxStrict的cookie。跨站请求,对于HTTPS协议的API返回的cookie,如果设置了属性:secure; samesite=none,则浏览器会存储cookie,XHR请求也会带上目标域的cookie。对于HTTP协议的API不能存储cookie,在浏览器开发者工具,网络面板中可以看到set-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。

跨站一定跨域。

    原文作者:朱慧杰_
    原文地址: https://blog.csdn.net/zhj52666/article/details/120510485
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。

相关文章