設定 crossorigin=anonymous 反而出錯
http cors browser -可以下任一方法處理,
-
拿掉
script
標籤中的crossorigin=anonymous
。 -
在伺服器的回應中加入標頭
access-control-allow-origin: *
。
Why
為了安全, HTTP 多了一個叫 Cross-Origin Resource Sharing
(跨來源資源共用) 簡稱 CORS
的東西。
而基於安全考量,程式碼所發出的跨來源 HTTP 請求會受到限制。不管你是使用 XMLHttpRequest 及 Fetch 或其他利用這些物件的函式庫來取得資源。
這些程式都遵守同源政策(same-origin policy)。這代表除非使用符合的 CORS
標頭,否則就只能請求與其相同來源的 HTTP 資源。
What
- origin
-
origin 網域(domain) [+ 通訊協定(protocol) [+ 通訊埠(port)]]
- CORS
-
CORS
CORS
是一種藉由附加額外的 HTTP 標頭使瀏覽器能取得其他網域伺服器資源的機制。 當瀏覽器請求一個不是目前文件來源(origin),例如是來自於不同網域(domain)、通訊協定(protocol)或通訊埠(port)的資源時,會建立一個跨來源 HTTP 請求(cross-origin HTTP request)。 - crossorigin
-
Cross Origin 對<audio>、<img>、<link>、<script> 和 <video> 等標籤設定 CORS 。
How
crossorigin 有三個可選值
-
anonymous 設定
mode
為CORS
,不發送`user credentials`,並設定credentials mode
為same-origin
。
const res = await fetch("https://pie.dev/get", { method: "GET", mode: 'cors', credentials: "same-origin" });
-
use-credentials 設定
mode
為CORS
發送`user credentials`,設定credentials mode
為include
。
const res = await fetch("https://pie.dev/get", { method: "GET", mode: 'cors', credentials: "include" });
-
"" 等同 anonymous。
其他不在三者的值都算 anonymous。
而其沒有 crossorigin
屬性則是內定為是 No CORS
。
const res = await fetch("https://pie.dev/get", { method: "GET", mode: 'no-cors', });
user credentials (用戶憑據)包含項目
-
cookie
-
客戶端 SSL 證書
-
HTTP 身份驗證
credentials mode
-
omit 在請求中排除用戶憑據,回傳任何用戶憑據都會被忽略。
-
same-origin 在對同源 URL 的請求中包含用戶憑據,並使用從同源 URL 的回應的用戶憑據。
-
include 在請求中包含用戶憑據,並使用回應的用戶憑據。
PS. 可以將用戶憑據替換為 cookie
來理解。
錯誤原因
因為只要設了 crossorigin
,瀏覽器設定 mode
為 CORS
,也就會檢查請求標頭上的 Origin
是否吻合回傳的 Access-Control-Allow-Origin
。
例如,
// request headers origin: https://www.hokang.info // response headers access-control-allow-origin: https://www.hokang.info // or access-control-allow-origin: *
則代表吻合通過。
而不設 crossorigin
,瀏覽器的 mode
為 NO-CORS
,發出的請求也就不是 cross-origin HTTP request
,當然也不會處理 CORS 相關的屬性。
而原本 script
標籤中 src 屬性就支援可取得跨域的資源。
所以,當加上 crossorigin=anonymous
而回應中卻沒有 access-control-allow-origin: *
時,反而不吻合 CORS
的規範。
這時可以
-
拿掉
script
標籤中的crossorigin=anonymous
。 -
在伺服器的回應中加入標頭
access-control-allow-origin: *
。
那是不是在 script
標籤中的就都不要加入 crossorigin
屬性?
有無設定的差別在,
當 script
沒有通過 CORS`時,其發生錯誤只會傳最少資訊給 `window.onerror
。
而當 CORS
並通過檢查後,則對跨域內容發生的錯誤就能列出更詳細的錯誤訊息。