Same-Site and Same-Origin
之前總以為 same-site 的網站一定也是 same-origin,後來才發現並非如此,是兩個不同的定義。此篇將介紹 same-site 和 same-origin 的定義,讓往後與後端 RD 討論 cookie SameSite
和 Access-Control-Allow-Origin
header 設定時能更順利。
Origin
Origin (網域) 是 scheme (或稱 protocol)、hostname (或稱 domain),和 port 的組合。
https://www.example.com:443
以上方網址為例
- scheme 是
https
- hostname 是
www.example.com
- port 是
443
因此,網址 https:www.example.com:443/foo
的 origin 為 https:www.example.com:443
。
"same-origin" and "cross-origin"
有著同樣 origin 的網站會是 "same-origin"(同源);其餘則為 "cross-origin" (跨域/跨來源)。
origin A: https://www.example.com:443
origin B | "same-origin" or "cross-origin" to origin A |
---|---|
https://www.evil.com:443 |
cross-origin: different domains |
https://example.com:443 |
cross-origin: different subdomains |
https://login.example.com:443 |
cross-origin: different subdomains |
http://www.example.com:443 |
cross-origin: different schemes |
https://www.example.com:80 |
cross-origin: different ports |
https://www.example.com:443 |
same-origin: exact match |
https://www.example.com |
same-origin: implicit port number (443) matches |
跨來源資源共用(Cross-Origin Resource Sharing (CORS))
當 user agent 請求一個不同源的資源時,會建立一個跨來源 HTTP 請求(cross-origin HTTP request)。基於安全性考量,跨來源 HTTP 請求會受到限制,例如
XMLHttpRequest
和Fetch API
都遵守同源政策(same-origin policy)。這代表 API 除非使用 CORS 標頭,否則只能請求與應用程式相同網域的 HTTP 資源。
由於此篇著重比較 same-site 和 same-origin 的差別,所以若想知道更多跨來源資源共用的規範,請見 MDN Web Docs。
Site (eTLD + 1)
"Site" 是指 TLD (Top-level domain) 和它之前的 domain。TLDs 包含條列在 Root Zone Database 中的 domain,例如 .com
和 .org
。
以 https://www.example.com:443/foo
為例
- eTLD 是
.com
- site (eTLD + 1) 是
example.com
- eTLD 和 TLD 的差別下方會說明
不過也有另一類的 domain,像是 .co.jp
和 .github.io
。這類 domain 如果只用 .jp
和 .io
作為 TLD 去定義 site 是不足夠的,而且也缺乏廣泛適用的邏輯去判斷。所以出現了表列的 eTLDs (effective TLDs),被條列在 Mozilla Public Suffix List 中。site 也被稱為 eTLD + 1
。
以 https://my-project.github.io
為例
- eTLD 是
.github.io
- site (eTLD + 1) 是
my-project.github.io
"same-site" and "cross-site"
有相同 eTLD + 1 的網站為 "same-site";其餘則為 "cross-site"。
site A: https://www.example.com:443
site B | "same-site" or "cross-site" to site A |
---|---|
https://www.evil.com:443 | cross-site: different domains |
https://login.example.com:443 | same-site: different subdomains don't matter |
http://www.example.com:443 | same-site: different schemes don't matter |
https://www.example.com:80 | same-site: different ports don't matter |
https://www.example.com:443 | same-site: exact match |
https://www.example.com | same-site: ports don't matter |
而 cats.github.io
和 dogs.github.io
為 cross-site,因為它們的 eTLD + 1 不同。
"schemeful same-site"
從上述的定義中可以知道,scheme 是否相同不影響 "same-site" 的判斷,但為了避免 HTTP 被以 weak channel 使用,協定開始商議將 scheme 納入判斷中,稱為 "schemeful same-site"。
如此一來,https://www.example.com:443
和 http://www.example.com:443
便為 "cross-site",因為它們的 scheme 不同。
Chrome 80 後針對第三方 cookie 的調整
Chrome 80+ 後將對所有未設定
SameSite
屬性的 Set-Cookie 預設為SameSite=Lax
,意味著除了 top level navigate + GET 的請求行為外,其餘 cross-site request 送發 cookie 的行為將預設被關閉。
SiteSite
values
SameSite=None
(withSecure
)SameSite=Lax
SameSite=Strict
更詳細的說明請見 Chrome 80 後針對第三方 Cookie 的規則調整
How to check if a request is "same-site", "same-origin", or "cross-site"
部分瀏覽器會在請求的 HTTP header 中附上 Sec-Fetch-Site
值,不過目前普及率不算高。
Sec-Fetch-Site
會是以下幾個值:
cross-site
same-site
(沒區分 "schemeful same-site")same-origin
none