跨站(cross-site)、跨域(cross-origin)、SameSite与XMLHttpRequest.withCredentials跨站(cross-site)与跨域(cross-origin)
- 跨站(cross-site):指的是两个站点(即两个不同域名或子域名下的资源)之间的交互。跨站通常意味着两个站点之间没有直接的信任关系,因此浏览器会实施更严格的安全策略。
- 跨域(cross-origin):跨域是指浏览器出于同源策略的限制,不允许不同源的文档或脚本相互操作。同源策略要求协议、域名和端口三者完全相同。跨域请求通常需要通过CORS(跨源资源共享)机制来实现。
跨站一定跨域,但跨域不一定跨站。例如,web.wjchi.com与service.wjchi.com具有相同的二级域名,可以看作是同站不同源(same-site, cross-origin),而web.github.io与service.github.io则是不同的站点不同的源(cross-site, cross-origin)。
SameSite
- SameSite属性是Set-Cookie HTTP响应头的一部分,用于声明cookie是否应该被限制在第一方或同站上下文中。
- SameSite有两个主要值:Lax和Strict。Lax允许GET请求携带cookie(如链接点击、表单提交等),但不允许跨站请求(如XHR、Fetch等)携带cookie。Strict则更加严格,不允许任何跨站请求携带cookie。
- 当设置为None时,表示cookie可以被跨站请求携带,但此时必须同时设置Secure属性,即cookie只能通过HTTPS传输。
XMLHttpRequest.withCredentials
- XMLHttpRequest.withCredentials属性是一个布尔值,指示跨站Access-Control请求是否应该使用凭据(如cookies、授权头或TLS客户端证书)。
- 默认情况下,withCredentials为false,即XHR请求不会携带cookie。当设置为true时,XHR请求会携带当前域的cookie,并且响应中的cookie也会被浏览器存储(如果服务器允许的话)。
- 需要注意的是,如果前端XHR请求中设置withCredentials为true,但后台API未设置Access-Control-Allow-Credentials为true,或者Access-Control-Allow-Origin的值为*,则会报错。因为CORS协议不允许同时指定通配符(任何)来源和凭据。
测试案例与结论
- same-origin:无论XMLHttpRequest.withCredentials是true还是false,浏览器均可存储cookie,XHR请求中均会带上cookie。
- 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;对于HTTPS协议的API,如果设置了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。
综上所述,跨站、跨域、SameSite与XMLHttpRequest.withCredentials是Web安全中非常重要的概念。理解这些概念及其相互作用,有助于开发更安全、更可靠的Web应用。