Web 开发中的 Origin 和 Site
Cross-Origin、Cross-Site、Same-Origin 和 Same-Site 是 Web 开发中常见的几个词,要是概念不清的话,很容易弄混。本文是对 Origin 和 Site 这两个概念的简单总结。
URL
一个 URL 可包含 scheme、uername、password、host、port、path、query 和 fragment 等信息。
以 https://tom:123456@example.com:8000/search?q=text#hello 为例,URL 包含的各项信息如下:
| Scheme | Username | Password | Host | Port | Path | Query | Fragment |
|---|---|---|---|---|---|---|---|
"https" |
"tom" |
"123456" |
"example.com" |
8000 |
"search" |
"q=text" |
"hello" |
Origin
一个 Origin 可看成是一个 Tuple:(scheme, host, port)。如果两个 Origin 的 scheme、host 和 port 都相同,则两个 Origin 被视为 Same-Origin,否则被视为 Cross-Origin(CORS 就是 Cross-Origin Resource Sharing)。
Tuple 的性质:
\((a_1, a_2, \ldots, a_n) = (b_1, b_2, \ldots, b_n)\) 当且仅当 \(a_1 = b_1, a_2 = b_2, \ldots, a_n = b_n\)
| URL A | URL B | Same-Origin / Cross-Origin |
|---|---|---|
| https://abc.com:443 | http://abc.com:443 | Cross-Origin(scheme 不同) |
| https://abc.com:443 | https://www.abc.com:443 | Cross-Origin(host 不同) |
| https://abc.com:443 | https://abc.com:500 | Cross-Origin(port 不同) |
| https://abc.com:443 | https://abc.com:443 | Same-Origin(三个元素都匹配) |
| https://abc.com:443 | https://abc.com | Same-Origin(scheme 为 https 时,port 默认为 443) |
| https://abc.com/foo:443 | https://abc.com/bar:443 | Same-Origin(三个元素都匹配) |
Site
一个 Site 也可以看成是一个 Tuple:(scheme, registrable-domain-or-host)。Same-Site 和 Cross-Site 的判断方法也类似。
其中,registrable-domain-or-host 的定义如下:
-
如果
host的registrable domain不为null,则registrable-domain-or-host等于registrable domain的值。 -
如果
host的registrable domain为null,则registrable-domain-or-host等于host的值。
与 registrable domain 相关的一个概念是 public suffix(别名:effective top-level domain / eTLD),两者的算法可见 Public Suffix List。
如果一个 host 的 public suffix 为 null 或者等于 host,其 registrable domain 的值为 null;否则,其 registrable domain 的值为 public suffix 加上前一个 label(也被称作 eTLD + 1)。
| Host | Public Suffix | Registrable Domain | Registrable Domain or Host |
|---|---|---|---|
| com | com | <null> | com |
| example.com | com | example.com | example.com |
| www.example.com | com | example.com | example.com |
| sub.www.example.com | com | example.com | example.com |
| EXAMPLE.COM | com | example.com | example.com |
| github.io | github.io | <null> | github.io |
| abc.github.io | github.io | github.io | abc.github.io |
| URL | Site |
|---|---|
| https://abc.com:443 | ("https", "abc.com") |
| https://abc.com/foo:443 | ("https", "abc.com") |
| https://whichxjy.github.io | ("https", "whichxjy.github.io") |
在 WHATWG 文档的定义中,Same-Site 的判断包括 scheme 的相等,这在某些文档中是不必要的。这种包括 scheme 判断的 Same-Site 也被称为 Schemeful Same-Site。
| URL A | URL B | Same-Site / Cross-Site |
|---|---|---|
| https://abc.com:443 | http://abc.com:443 | Cross-Site(scheme 不同) |
| https://abc.com:443 | http://def.com:443 | Cross-Site(registrable domain 不同) |
| https://abc.com:443 | https://www.abc.com:443 | Same-Site |
| https://abc.com:443 | https://abc.com:500 | Same-Site |
| https://abc.com:443 | https://abc.com:443 | Same-Site |
| https://abc.com:443 | https://abc.com | Same-Site |
| https://abc.com/foo:443 | https://abc.com/bar:443 | Same-Site |