同源、跨域、同站、跨站、Cookie访问限制

1,283 阅读3分钟

域名

顶级域名、一级域名、二级域名

.com 顶级域名/一级域名,更准确的说叫顶级域
baidu.com 二级域名,更准确的说叫二级域
tieba.baidu.com 三级域名,更准确的说叫三级域
detail.tieba.baidu.com 四级域名,更准确的说叫四级域

子域名

子域名是在域名系统等级中,属于更高一层域的域。比如,mail.example.com 和 calendar.example.com是example.com的两个子域,而example.com则是顶级域.com的子域

同源策略

浏览器有同源策略,如果两个url的协议、域名、端口完全一致才是同源,有一个不一致就是跨域

同源策略限制

  1. DOM:禁止操作非源页面的DOM与JS对象

这里主要场景是iframe跨域的情况,非同源的iframe是限制互相访问的

  1. XmlHttpRequest:禁止使用XHR对象向不同源的服务器发起HTTP请求,即不能发送跨域ajax请求

主要用来防止CSRF攻击

  1. 本地存储:Cookie、LocalStorage和IndexDB无法跨域读取

跨域(cross-origin)

违反同源策略就是跨域

跨站(cross-site)

只有两个URL的eTLD+1相同即是同站(Same Site),不需要考虑协议和端口

eTLD:有效顶级域名/一级域名,如.com.co.uk.github.io.top

eTLD+1:有效顶级域名+二级域名,如 taobao.com,baidu.com

跨站一定跨域,跨域未必跨站(子域名、三级域名等)

如何检查请求是否为 同站、同源、跨站

Chrome发送请求时会附带一个Sec-Fetch-Site HTTP Header ,Sec-Fetch-Site表示一个请求发起者的来源与目标资源来源之间的关系,这个Header将有以下值之一

  • cross-site 跨站/跨域
  • same-site 同站
  • same-origin 同源
  • none

通过检查Sec-Fetch-Site的值,可以确定请求是同站、同源还是跨站

示例

Sec-Fetch-Site: same-origin 示例

https://mysite.example/foo.json 从网页发起的 https://mysite.example (具有相同的端口)是同源的请求

Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Sec-Fetch-Site: cross-site示例
  1. 例如,从 https://example.com的页面发起请求到 ``https://api.example.com
  2. 例如,从 ``https://example.com的页面点击链接跳转到 ``https://example.net
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site

当浏览器检测到请求中的Sec-Fetch-Site: cross-site,在跨站请求中,浏览器通常会遵循同源策略,该策略要求请求只能访问与其来源相同的资源,即浏览器默认情况下不会将跨站请求的Cookie发送到服务器,但是当设置SameSite为none和Secure时是可以发送的

Cookie访问限制 --- 重点

浏览器的同源策略将会限制不同源间的访问,对于跨站和跨域来说对访问Cookie的影响也是不同的。

  1. 同源

    1.   无限制,浏览器均可存储Cookie,请求中均携带Cookie
  2. 跨域

    1.   前提前端请求设置withCredentials为true

    2. 同站请求

      1. 对于HTTPS,浏览器自动携带相应的Cookie,这是默认行为
      2. 对于HTTP,浏览器自动携带相应的Cookie,这是默认行为
    3. 跨站请求

      1. 对于HTTPS,浏览器默认不会携带Cookie,

        1. 服务端设置:必须设置Access-Control-Allow-Credentialstrue,同时还需要设置Access-Control-Allow-Origin头部字段来指定允许访问的源
        2. 客户端设置:withCredentials设置为true,同时Set-Cookie: name=value; Secure; SameSite=None
      2. 对于HTTP,浏览器默认不会携带Cookie

SameSite属性

  • SameSite=None:允许跨站发送Cookie,适用于需要在跨域请求中携带Cookie的情况,需要同时配合Secure属性,即Cookie只能在Https中发送
  • SameSite=Strict:禁止跨站发送Cookie,默认值。只有在同站请求中携带Cookie,跨站请求中不会携带Cookie
  • SameSite=Lax:限制跨站发送Cookie,仅允许在安全跨站请求中携带Cookie(get请求),在POST请求、iframe或Ajax等情况下,将不会携带Cookie