服務端配置 CORS(跨域資源共享)的原理本質是 瀏覽器與服務器之間的安全協商機制。其核心在于服務器通過特定的 HTTP 響應頭聲明允許哪些外部源(Origin)訪問資源,瀏覽器根據這些響應頭決定是否放行跨域請求。以下是詳細原理分解:
一、核心流程:瀏覽器與服務端的協作機制
場景:網頁 https://web.com
請求 https://api.com/data
-
瀏覽器發起跨域請求
- 自動在請求頭中添加
Origin: https://web.com
(表明請求來源)。
- 自動在請求頭中添加
-
服務端響應
- 檢查
Origin
值是否在允許列表中。 - 若允許,則在響應頭中添加 CORS 相關字段(如
Access-Control-Allow-Origin: https://web.com
)。 - 若拒絕,不添加 CORS 頭或返回錯誤(瀏覽器會攔截響應)。
- 檢查
-
瀏覽器驗證響應頭
- 檢查響應頭是否包含
Access-Control-Allow-Origin
且值與當前Origin
匹配(或為*
)。 - 驗證通過 → 解除攔截,網頁可讀取響應數據。
- 驗證失敗 → 拋出 CORS 錯誤(如
No 'Access-Control-Allow-Origin' header
)。
- 檢查響應頭是否包含
二、關鍵 HTTP 響應頭字段解析
服務器通過以下頭字段聲明跨域規則:
響應頭字段 | 作用 | 示例 |
---|---|---|
Access-Control-Allow-Origin | 必選,聲明允許訪問的源(域名) | https://web.com 或 * |
Access-Control-Allow-Methods | 聲明允許的 HTTP 方法(如 GET、POST) | GET, POST, PUT |
Access-Control-Allow-Headers | 聲明允許客戶端攜帶的請求頭(如 Content-Type ) | Content-Type, Authorization |
Access-Control-Allow-Credentials | 是否允許發送 Cookie 等憑證(需客戶端設置 withCredentials: true ) | true |
Access-Control-Max-Age | 預檢請求(OPTIONS)的緩存時間(秒),減少重復預檢 | 86400 (24小時) |
?? 注意:若請求需攜帶 Cookie(憑證),則:
- 服務端必須設置
Access-Control-Allow-Credentials: true
- 服務端的
Access-Control-Allow-Origin
不能為*
,必須明確指定域名(如https://web.com
)- 客戶端需設置
withCredentials: true
(如 Fetch API 或 Axios)。
三、預檢請求(Preflight Request):復雜請求的二次確認
當請求滿足以下任一條件時,瀏覽器會先發送 OPTIONS 預檢請求(非簡單請求):
- 使用了
PUT
、DELETE
等非簡單方法(簡單方法僅限GET
、POST
、HEAD
)。 - 攜帶了自定義請求頭(如
Authorization
)。 Content-Type
為application/json
等非簡單類型(簡單類型僅限application/x-www-form-urlencoded
、multipart/form-data
、text/plain
)。
預檢請求工作流程:
四、CORS 的安全本質:服務端控制權限
-
主動權在服務端
- 瀏覽器只是執行者,實際放行權由服務端通過響應頭控制。
- 若服務器未返回正確的 CORS 頭,即使接口本身能正常響應(如用 Postman 測試成功),瀏覽器仍會攔截。
-
防御惡意網站
- 假設用戶訪問了惡意網站
evil.com
,該網站嘗試請求bank.com
的 API:bank.com
的服務器檢測到Origin: evil.com
不在白名單中 → 不返回 CORS 頭。- 瀏覽器攔截響應 →
evil.com
無法讀取bank.com
的數據。
- 假設用戶訪問了惡意網站
五、配置示例:Node.js 中的 CORS 中間件
const express = require('express');
const cors = require('cors');const app = express();// 基礎配置:允許所有源訪問(慎用!)
app.use(cors());// 精細化配置(推薦)
app.use(cors({origin: 'https://web.com', // 僅允許指定源methods: ['GET', 'POST'], // 允許的方法allowedHeaders: ['Content-Type'], // 允許的請求頭credentials: true, // 允許攜帶憑證maxAge: 86400 // 預檢緩存時間
}));app.get('/data', (req, res) => {res.json({ data: "跨域數據返回成功!" });
});
六、常見誤區澄清
誤區 | 真相 |
---|---|
“CORS 是服務端的安全漏洞” | CORS 是安全機制,沒有它瀏覽器會默認禁止跨域 |
“JSONP 能替代 CORS” | JSONP 僅支持 GET,且存在安全風險(如 XSS) |
“前端代碼可繞過 CORS 限制” | 瀏覽器會強制檢查響應頭,前端無法繞過 |
“服務端不配置 CORS = 接口無法訪問” | 接口仍可被 curl、Postman 等工具調用,但瀏覽器會攔截 |
總結:CORS 的核心原理
通過這一機制,CORS 在不犧牲安全性的前提下實現了可控的跨域資源共享,成為現代 Web 開發的基石技術。