1. CORS 產生的原因
CORS 全稱為(Cross-Origin Resource Sharing:跨站資源共享),跨域請求是由於瀏覽器的同源策略(Same-Origin Policy)引起的,那麼 CORS 的產生和瀏覽器的同源策略有關係,我們先了解什麼是同源策略。
2. 什麼是同源策略
SOP 是所有的現代瀏覽器都具備的安全措施,它不允許從一個加載的js腳本和資源的 Origin 域與另一個 Origin 域進行交互。換句話説,如果您的網站是 www.a.com,則您無法向 www.b.com 發出XHR請求。
如果説 SOP 是限制跨源訪問的一種方式,那麼 CORS 則是一種繞過 SOP 限制並允許您的前端向服務器提出合法請求的方法。
3. 什麼是 Origin
Origin 翻譯為源(域),在 CORS 上下文中 Origin 由三個元素組成:
Origin = 協議 + 域名 + 端口
協議(Protocol) :例如,http:// 或 https://
域名(Domain) :例如,www.google.com
端口(Port) :例如,80(默認HTTP端口)或443(默認HTTPS端口)
同源策略就是:不允許不同的 ip、端口、協議的應用在瀏覽器內進行互相資源共享、請求調用。也就是説只有上述三個元素都匹配時,我們才會認為兩個 URL 具有相同的來源,否則,有任何一個不相同都認為不同源。
具體式例:
4. 什麼是 CORS?
CORS 是一種機制,它使用額外的 HTTP 頭來告訴瀏覽器允許一個網頁從另一個域(不同於該網頁所在的域)請求資源。這樣可以在服務器和客户端之間進行安全的跨域通信。
CORS有兩種類型的請求:“simple” 簡單請求和 “preflight” 預檢請求,根據請求方法的不同由瀏覽器確定使用哪種請求。
simple 簡單請求:
如果符合以下所有條件,則API請求被視為簡單請求:
- API方法是以下方法之一:GET,POST或HEAD。
- Content-Type請求頭包含:application/x-www-form-urlencoded,multipart/form-data,text/plain
對於 GET、HEAD 和某些 POST 請求,瀏覽器直接附加 Origin 頭髮送請求,服務器在響應中添加 CORS 相關字段即可,無需預檢。如果您的API請求被視為 simple 簡單請求,這個請求就可以直接被髮送給服務器。服務器使用 CORS HTTP Headers進行響應,瀏覽器將檢查 Access-Control-Allow-Origin 後決定這個請求是否可以突破同源策略的限制,進行下一步的處理。
preflight預檢請求:
如果您的 API 請求不滿足成為簡單請求的標準(最常見不滿足簡單請求標準的Content-Type值為application/json),則瀏覽器將在發送實際請求之前發出預檢請求。
當一個網頁向不同源發出請求時,CORS 會通過以下幾個步驟來處理:
- 預檢請求(Preflight Request):對於某些類型的請求(如使用 HTTP 方法 PUT、DELETE,或者請求帶有非簡單頭部),瀏覽器會首先發送一個 OPTIONS 請求,這個請求稱為“預檢請求”。服務器收到這個請求後,會返回一個響應頭部,指明實際請求是否被允許。
- 實際請求(Actual Request):如果預檢請求通過,瀏覽器會繼續發送實際的請求。
- 響應頭部(Response Headers):服務器在響應中會包含一些特定的 CORS 頭部,如 Access-Control-Allow-Origin,以指示哪些域名可以訪問資源。
舉一個例子,我們嘗試使用 GET 請求 https://example.com/status,Content-Type 是application/json,所以瀏覽器認為它不符合一個簡單請求的標準,因此瀏覽器會在發出實際請求之前發出預檢請求,這個預檢請求是使用 HTTP 的 OPTIONS 方法發出的:
5. 如何處理 CORS
[]()服務端處理
後端設置響應頭,允許特定源的請求。
設置基礎響應頭\
在服務器響應中添加以下頭部:
Access-Control-Allow-Origin: <允許的源> # 如 "*"(允許所有)或 "https://example.com"
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS # 允許的HTTP方法
Access-Control-Allow-Headers: Content-Type, Authorization # 允許的請求頭
Access-Control-Allow-Credentials: true # 允許攜帶憑證(如Cookie),需與具體源配合使用
處理預檢請求(Preflight Request)\
對 OPTIONS 方法的請求返回允許的CORS頭,無需處理業務邏輯:
// Express示例
app.options('/api', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', 'https://example.com');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
res.sendStatus(204);
});
代理服務器
通過同域的反向代理轉發請求,避開瀏覽器限制。
步驟(以Nginx為例):
修改Nginx配置:
server {
listen 80;
server_name yourdomain.com;
location /api/ {
proxy_pass http://backend-server:3000/; # 轉發到後端服務
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
前端請求同域接口(如 /api/data),Nginx將請求代理到實際後端。
通常來説,在服務器解決 CORS 是一種比較常見和徹底的方式,我們可以在服務器靈活的設置允許跨域訪問的域名或者地址。
6. 總結
CORS 是現代 Web 開發中常見的問題,理解 CORS 的工作原理,可以幫助我們有效地解決跨域請求的問題。