跳到主要內容

初探 Vue 呼叫 API 出現 CORS 跨來源資源共享 問題原因

提要: 

在 {初探Vue 與 Spring boot 的對話} 專案 ,前端 Vue 應用程式 串接 後端 API 伺服器 ,axios 呼叫 API 時出現以下,”無法取得回應內容 (No 'Access-Control-Allow-Origin' header is present on the requested resource):” 錯誤訊息,根據查找相關資料 ,出現以下原因。


瀏覽器開發工具 錯誤訊息 畫面



錯誤原因:


Access to XMLHttpRequest at ” from origin ‘http://localhost:8080’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource”

瀏覽器為了安全考量,實施了同源政策。

當您的前端應用程式 (http://localhost:8080) 嘗試呼叫一個不同來源 (不同協議、不同域名或不同埠號) 的 API 伺服器 (http://localhost:8088) 時,瀏覽器會主動阻止這個請求,除非伺服器明確地允許這個跨來源的存取。


同源政策限制(Same-Origin Policy):

同源政策限制了程式碼和不同網域資源間的互動,同源是指兩份網頁具備相同協定、埠號(如果有指定)以及主機位置


範例: 表列哪些 URL 與 URL http://www.example.com/api/p1 屬於同源:

URL                                                   | 結果  | 原因

---------------------------------------------------------------------

http://www.example.com/api/p2     |    | 只有路徑不同

---------------------------------------------------------------------

http://www.example.com/api2/p1    |    | 只有路徑不同

---------------------------------------------------------------------

http://www.example.com:81/api/p1 |    | 不同埠(未指定 http:// 默認為80)

---------------------------------------------------------------------

https://www.example.com/api/p1    |    | 不同協定(https)

---------------------------------------------------------------------

http://example.net/api/p1                 |    | 不同域名

---------------------------------------------------------------------



為什麼需要 CORS (Cross-Origin Resource Sharing)跨來源資源共享?


CORS 是一種基於 HTTP 標頭的機制,允許伺服器指示瀏覽器允許從除其自身以外的任何來源(網域、協定或連接埠)加載資源。

主要是同源政策限制規定,網頁只能向相同來源(協議、域名、埠號都相同)的伺服器發送請求。

如果您的前端網頁(A 來源)想向另一個伺服器(B 來源)請求資料。瀏覽器會主動阻止,為防止惡意的網站在使用者不知情的情況下盜取其他網站的資料。

CORS 機制就是允許伺服器 明確地告訴 瀏覽器:「我是 B 來源,我同意 A 來源來存取我的資料。」


舉個簡單例子:

前端 http://example.com:8080 (F 來源)您的 Vue 應用程式

後端 API 伺服器 https://api.example.com (B 來源) 使用者資料的伺服器


當您的前端網頁(http://example.com:8080) 嘗試用 JavaScript 呼叫 API (https://api.example.com) 獲取使用者清單時:

1.來源不相同: 協議(http vs https)、網域(example.com vs api.example.com) 和埠號 (8080 vs 預設 443) 都不同,這是跨來源請求。

2. 瀏覽器檢查: 瀏覽器發現這是跨來源請求,它會先檢查伺服器(B 來源)的回應。

3.CORS 處理:

    如果 B 伺服器在其回應標頭中加入了: Access-Control-Allow-Origin: http://example.com:8080

        結果: 瀏覽器認為這是安全的,允許存取,請求成功。

    如果 B 伺服器 沒有 這個標頭:

        結果: 瀏覽器認為 B 伺服器不允許 F 來源存取,因此會拋出您之前遇到的 CORS 錯誤,請求失敗。



參看:

同源政策限制(Same-Origin Policy):

https://developer.mozilla.org/zh-CN/docs/Web/Security/Defenses/Same-origin_policy  (簡中)

https://developer.mozilla.org/zh-TW/docs/Web/Security/Defenses/Same-origin_policy  (繁中)

https://www.w3.org/Security/wiki/Same_Origin_Policy


跨來源資源共享(CORS):

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Guides/CORS  (簡中)

https://developer.mozilla.org/zh-TW/docs/Web/HTTP/Guides/CORS  (繁中)

留言

這個網誌中的熱門文章

初探 Vue 與 Spring boot 的對話之Frontend (Vue-Frontend)

  Front-end Vue 使用 REST API 建立 Vite 專案 可參考 { Vue 3 初探}  文章 danny@Danny-Yu projects % npm create vite@latest Need to install the following packages: create-vite@8.2.0 Ok to proceed? (y) y > npx > "create-vite" │ ◇   Project name: │   vue-frontend │ ◇   Select a framework: │   Vue │ ◇   Select a variant: │   TypeScript │ ◇   Use rolldown-vite (Experimental)?: │   No │ ◇   Install with npm and start now? │   Yes │ ◇   Scaffolding project in /Users/danny/Desktop/projects/vue-frontend... │ ◇   Installing dependencies with npm... added 47 packages, and audited 48 packages in 27s 6 packages are looking for funding   run `npm fund` for details found 0 vulnerabilities │ ◇   Starting dev server... > vue-frontend@0.0.0 dev > vite   VITE v7.2.4   ready in 411 ms   ➜   Local:   http://localhost:5173/   ➜   Network: use --host to expose   ➜   press h + enter to show...

初探 Spring 中的循環依賴

原因: 當兩個或多個 bean 直接或間接地相互依賴時, 就會出現 Circular Dependency (循環依賴) 如: Bean A -> Bean B -> Bean A import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class BeanA {          @Autowired     private BeanB beanB;     public String sayHi() {         return "Hi! 我是 Class A.";     } } import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class BeanB {          @Autowired     private BeanA beanA;     public String sayHi() {         return "Hi! 我是 Class B.";     } } 編譯時不會出現問題 danny@Danny-Yu demo % mvn clean install -Dmaven.test.skip=true                           ... ... [INFO] Installing /Users/danny/Desktop/projects/demo/target/dem...