django中同源策略和跨域解決方案
阿新 • • 發佈:2018-12-21
一 同源策略
1.1何謂同源?
- 如果兩個頁面的協議,埠(如果有指定)和域名都相同,則兩個頁面具有相同的源。
- 舉個例子:
- 下表給出了相對http://a.xyz.com/dir/page.html同源檢測的示例:
1.2什麼是同源策略?
- 同源策略是瀏覽器的一個安全功能,不同源的客戶端指令碼在沒有明確授權的情況下,不能讀寫對方資源。所以xyz.com下的js指令碼採用ajax讀取abc.com裡面的檔案資料是會被拒絕的。
- 同源策略限制了從同一個源載入的文件或指令碼如何與來自另一個源的資源進行互動。這是一個用於隔離潛在惡意檔案的重要安全機制。
1.3不受同源策略限制的?
- 頁面中的連結,重定向以及表單提交是不會受到同源策略限制的。
- 跨域資源的引入是可以的。但是js不能讀寫載入的內容。如嵌入到頁面中的<script src="..."></script>,<img>,<link>,<iframe>等。
二 CROS(跨域資源共享)
CORS需要瀏覽器和伺服器同時支援。目前,所有瀏覽器都支援該功能,IE瀏覽器不能低於IE10。
整個CORS通訊過程,都是瀏覽器自動完成,不需要使用者參與。對於開發者來說,CORS通訊與同源的AJAX通訊沒有差別,程式碼完全一樣。瀏覽器一旦發現AJAX請求跨源,就會自動新增一些附加的頭資訊,有時還會多出一次附加的請求,但使用者不會有感覺。
因此,實現CORS通訊的關鍵是伺服器。只要伺服器實現了CORS介面,就可以跨源通訊。
三 CORS基本流程
3.1瀏覽器將CORS請求分成兩類:
- 簡單請求(simple request)
- 非簡單請求(not-so-simple request)
瀏覽器發出CORS:簡單請求.只需要在頭資訊之中增加一個Origin欄位。
瀏覽器發出CORS:非簡單請求.會在正式通訊之前,增加一次HTTP查詢請求,稱為"預檢"請求(preflight)。瀏覽器先詢問伺服器,當前網頁所在的域名是否在伺服器的許可名單之中,以及可以使用哪些HTTP動詞和頭資訊欄位。只有得到肯定答覆,瀏覽器才會發出正式的XMLHttpRequest請求,否則就報錯。
四 CORS兩種請求詳解
4.1只要同時滿足以下兩大條件,就屬於簡單的請求:
(1) 請求方法是以下三種方法之一: HEAD GET POST (2)HTTP的頭資訊不超出以下幾種欄位: Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain
凡是不同時滿足上面兩個條件,就屬於非簡單請求。
瀏覽器對這兩種請求的處理,是不一樣的。
4.2簡單請求和非簡單請求的區別?
簡單請求:一次請求
非簡單請求:兩次請求,在傳送資料之前會先發一次請求用於做“預檢”,只有“預檢”通過後才再傳送一次請求用於資料傳輸。
- 請求方式:OPTIONS - “預檢”其實做檢查,檢查如果通過則允許傳輸資料,檢查不通過則不再發送真正想要傳送的訊息 - 如何“預檢” => 如果複雜請求是PUT等請求,則服務端需要設定允許某請求,否則“預檢”不通過 Access-Control-Request-Method => 如果複雜請求設定了請求頭,則服務端需要設定允許某請求頭,否則“預檢”不通過 Access-Control-Request-Headers
支援跨域,簡單請求:
伺服器設定響應頭:Access-Control-Allow-Origin = '域名' 或 '*'
支援跨域複雜請求:
由於複雜請求時,首先會發送“預檢”請求,如果“預檢”成功,則傳送真實資料。
- “預檢”請求時,允許請求方式則需伺服器設定響應頭:Access-Control-Request-Method
- “預檢”請求時,允許請求頭則需伺服器設定響應頭:Access-Control-Request-Headers
五 Django專案中的應用
在返回結果中加入允許資訊(簡單請求):
def test(request): import json obj=HttpResponse(json.dumps({'name':'lqz'})) # obj['Access-Control-Allow-Origin']='*' obj['Access-Control-Allow-Origin']='http://127.0.0.1:8004' return obj
放到中介軟體中處理複雜和簡單請求:
from django.utils.deprecation import MiddlewareMixin
class MyCorsMiddle(MiddlewareMixin): def process_response(self, request, response): # 簡單請求: # 允許http://127.0.0.1:8001域向我發請求 # ret['Access-Control-Allow-Origin']='http://127.0.0.1:8001' # 允許所有人向我發請求 response['Access-Control-Allow-Origin'] = '*' if request.method == 'OPTIONS': # 所有的頭資訊都允許 response['Access-Control-Allow-Headers'] = '*' return response
在settings中配置即可,在中介軟體中的位置可以隨意放置.