Cross-origin 跨域請求

donggg發表於2022-02-14

Cookie

  • 1993 迎來了 img 標籤,這是 web 第一次迎來了資源載入

    <img src="foo.jpg" />
    <img src="http://somewhere.com/foo.jpg" />
  • 1994

    Set-Cookie: foo=bar
  • 1995

    <img src="http://somewhere.com/foo.jpg" />
    <script src="http://somewhere.com/foo.js" ></script>
    <iframe src="http://somewhere.com/foo.html" />

    起初這樣的設計會導致嚴重的問題:無論是網站,只要包含上面的標籤都會攜帶 cookie 訪問。

更不用說這樣的請求了。

<form action="http://somewhere.com./submit"></form>

因此 http 通過 Origin 這個頭來限制訪問

  • 1999

    // XMLHttpRequest 的前身
    new ActiveXObject('Microsoft.XMLHTTP');
  • 2008

    var req = new XMLHttpRequest()
    req.addEventListener('load', loadListener);
    req.open('GET', 'https://example.com/data.txt');
    req.send();

現在

const res = await fetch('http://example.com/data.txt', {
    credentials: 'include',
});

現在我們已經使用這樣方式請求,但是同樣也要受限於伺服器是否響應 (下面就是伺服器為什麼有的會響應)

跨域資源共享(CORS)

我們通過 access-control-allow-origin 來決定那些那資源可以被跨域訪問,例如設定 access-control-allow-origin: * 允許所有資源可以被訪問 。並且通過設定 credential 來決定是否攜帶 cookie

access-control-allow-credentials: true 決定是否允許你訪問 cookie。但是同時你必須明確通過 access-control-allow-origin 指出跨域訪問的網址。

這些頭資訊已經在我們通過瀏覽器發出的請求中設定好了,我們不需要特別關心。例如我們通過 <form> 傳送時請求時, Content-Type 已經設定成例如 x-www-form-urlencoded

一個小知識點:你可以傳送設定成 Content-type: text/plainPOST 請求。例如通過 <form> 來傳送 email,只要保證了像 x-www-form-urlencoded 的空行間隔。

Referrer

從一個網站跳到另外一個網站時,會有這個頭資訊

Origin

Referrer 不可靠,所以有了 Origin 這個頭資訊。Origin 會出現在跨域的請求中。

通常來說,我們限制了 access-control-allow-origin 網站就已經足夠安全。

除了CORSGET 請求外,其他的GET 請求都不帶 Origin。可以通過判斷 Origin 得知這個是不是跨域的請求。

跨域中危險的 cookie

當我們不帶 cookie 發出請求時,可能會引發很多問題。首先我們要知道什麼情況 access-control-allow-origin: * 時是安全的 ,例如家中分佈的IoT 裝置,本地的請求。除此之外都可能引發CSRF 攻擊。

限制 cookie

例如通過圖片追蹤。當你訪問 other.com 時,<img /> 會允許設定cookie 從而進行跟蹤。

<!-- site: other.com -->
<img src="http://statics.com/user-avatar-a.png" />

設定 SameSite: Strict | Lax | NoneLax 不允許 img iframe AJAX POST 表單攜帶 cookie (當前所在地站點是:other.com ) 。不過 Lax 允許<a>連結,預載入請求,GET 表單這3種情況的攜帶 cookie

Set-cookie: sessionid=1234567; SameSite=Lax; HttpOnly; Max-Age=3153600
SameSite: Strict 這會導致所有的跨域均不帶 cookie ,例如在非github 的網站上跳轉至 github 將不會攜帶 cookie ,此時 github 將顯示未登入。
httponly:不能通過 javasript 獲取 cookie

跨域資源策略(CORP)

Cross-Origin-Resource-Policy: same-site 標記為 same-site 的資源只能從相同站點載入。

Cross-Origin-Resource-Policy 響應頭會指示瀏覽器阻止對指定資源的無源跨域/跨站點請求。

在下面這個請求中加入 CORP 的頭資訊,圖片將載入失敗。

<!-- site: other.com -->
<img src="http://statics.com/user-avatar-a.png" />
Cross-Origin-Resource-Policy: same-site | same-origin |cross-origin

CORB

下面這個場景是無法通過同一個 cookie 處理,雖然你可以將 cookie 放在 html 的請求中。

<img src="http://example.com/secret.html" />

這個請求仍然會將 html 檔案的請求放到程式中,來表示當前請求處理完成。這可能會引起某些問題。Meltdown and Spectre

Cross-Origin-Read-Blocking 阻止跨域的請求動作,同時跨域的返回也會被阻止。例如上面的請求,將不會進入瀏覽器的處理程式中。

請求在進入程式前,會注意mine type 如果是 nosniff (nosniff 將阻止瀏覽器針對 content-type的一些優化)。Chrome 瀏覽器針對 html 檔案的請求並且不是跨域將會阻止。

CORB 是不頭資訊

跨域嵌入策略 (COEP)

Cross-Origin-Embedder-Policy: require-corp 文件只能從同一來源載入資源,或者顯式被標記為可從另一來源載入的資源。

為了從其他來源載入資源,需要支援跨域資源共享(CORS)或跨域資源策略(CORP)

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Resource-Policy: cross-origin

相關文章