CORS 即跨資源共享,是一種機制,它使用額外的 HTTP 頭來告訴瀏覽器 讓運行在一個 origin (domain) 上的 Web 應用被准許訪問來自不一樣源服務器上的指定的資源。 簡單來講,出於安全緣由,瀏覽器會限制從腳本內發起的跨域請求,如 XMLHttpRequest 和 Fetch。也就是說,在 Javascript 中,當咱們想發起一個跨域的 Ajax 請求,會受到瀏覽器的限制致使請求失敗。javascript
舉個例子: 在 http://mysite.com/index.html
中,發起一個 Ajax 請求到 http://api.yoursite.com/article/all/
,會失敗,若是打開控制檯看日誌,會看到相似以下的輸出:html
Access to XMLHttpRequest at 'http://api.yoursite.com/article/all/' from origin 'http://mysite.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
複製代碼
在如今開發常規 Web 項目的時候,即便在正式上線後使用統一域名訪問項目,也很難說在開發和聯調過程當中也使用統一域名,因此掌握跨域請求的處理仍是頗有必要的。前端
跨域請求的處理方法除了 CORS 外,還有 代理服務器、JSONP。java
一說到使用服務器的方式,咱們能夠立刻想到一個流行的反向代理服務器 Nginx,的確,咱們可使用 Nginx 的 proxy_pass
指令實現代理的目的,但這種方法每每很不直觀,且通常也須要前端同窗在本地搭建相關環境才能夠運做,能夠說是一個不怎麼樣的選擇。nginx
除了 Nginx 外,前端的同窗可能會說如今不少流行的框架都集成有這樣的功能,如 Vue.js 的 devServer
,前端同窗能夠在項目中編寫熟悉的 Javascript 代碼以實現請求的代理,最終實現跨域請求,方便聯調,但也侷限於開發時使用。django
JSONP 是利用了 src 引用靜態資源時不受跨域限制的機制,前端會先定義一個回調函數用來處理請求成功後的邏輯,並在請求服務端時告知服務端這個回調函數的名字,而服務端只須要把須要返回的數據按照 Javascript 的語法,放進回調函數中便可。 大概像這樣子:編程
<!-- http://mysite.com/index.html -->
<script> function callback(data) { // 處理 data console.log(data) } </script>
<script src="http://api.yoursite.com/article/all/?callbackFunc=callback"></script>
複製代碼
的確,JSONP 能夠成功獲取到數據,且回調函數也會被正確執行,但在使用 JSONP 以前,它的缺點你須要先了解:後端
說實話,如今在開發項目時已經不多使用 JSONP 了,這裏只是給同窗們瞭解瞭解。api
CORS 機制,容許 Web 應用服務器進行跨域訪問控制,從而使跨域數據傳輸得以安全。跨域
這裏以 Nginx 爲例,看看要怎樣才能作到跨域訪問控制。 咱們來看看如何配置吧:
http {
# 省略其餘...
server {
listen 80;
server_name api.yoursite.com;
charset utf-8;
location / {
include /usr/local/nginx/conf/cors;
// 省略其餘...
}
}
}
複製代碼
這樣,咱們 http://api.yoursite.com/
下的 API 就支持跨域請求了(不考慮程序代碼有限制的狀況)。
重點是 include /usr/local/nginx/conf/cors;
,下面來看看 cors 文件裏面的內容吧:
其核心的部分,是加入了 Access-Control-Allow-Origin
HTTP 頭,而其餘部分的內容,則是更細粒度的控制,如不一樣的請求方法也能夠設置不一樣的 HTTP 頭達到控制的目的。 搭配 Nginx 的 location
指令,咱們則能夠控制某些路徑下才開啓 CORS,以達到更細粒度的控制。
你們能夠在 enable-cors.org/server_ngin… 得到 cors 文件的內容。這個文件內容只是一個範本,並非惟一的寫法,你們在實際使用時按照需求自行修改便可。
若是你想更深刻了解 CORS 機制,能夠訪問 developer.mozilla.org/zh-CN/docs/…
理解了 CORS 機制的原理的話,這種問題不在話下。
這個網址提供了不一樣服務器、Web 框架、編程語言的實現方式,enable-cors.org/server.html…
忍不住吐槽,裏面恰恰沒有 Django 的實現方式,Django 的話,可使用 django-cors-headers
,在使用 Django 開發後端時,前端也能愉快的發起跨域請求了。
從技術的革新角度也好,從使用的便捷度也好,CORS 是一個更好的跨域請求的選擇。只須要(通常是)後端人員配置好,前端能夠不須要作任何額外的改變,就能夠調用後端 API 了。這種方法,不管是開發時或是正式上線後,均可以使用,無需考慮過大的差別性問題。
尚未用過 CORS 的同窗,趕忙嘗試一波吧。