1. 程式人生 > 實用技巧 >Django之corsheaders[跨域設定]

Django之corsheaders[跨域設定]

跨域請求

概述

在 HTML 中,<a>, <form>, <img>, <script>, <iframe>, <link> 等標籤以及 Ajax 都可以指向一個資源地址, 而所謂的跨域請求就是指:當前發起請求的域與該請求指向的資源所在的域不一樣。這裡的域指的是這樣 的一個概念:我們認為若協議 + 域名 + 埠號均相同,那麼就是同域。

安全問題

​ 通常,瀏覽器會對上面提到的跨域請求作出限制。瀏覽器之所以要對跨域請求作出限制,是出於安全方面

的考慮,因為跨域請求有可能被不法分子利用來發動CSRF攻擊。

跨域解決方法

JSONP

原理:
  • JSONP 是一種非官方的跨域資料互動協議
  • JSONP 本質上是利用 <script><img><iframe> 等標籤不受同源策略限制,可以從不同域載入並執行資源的特性,來實現資料跨域傳輸。
  • JSONP由兩部分組成:回撥函式和資料。回撥函式是當響應到來時應該在頁面中呼叫的函式,而資料就是傳入回撥函式中的JSON資料。
  • JSONP 的理念就是,與服務端約定好一個回撥函式名,服務端接收到請求後,將返回一段 Javascript,在這段 Javascript 程式碼中呼叫了約定好的回撥函式,並且將資料作為引數進行傳遞。當網頁接收到這段 Javascript 程式碼後,就會執行這個回撥函式,這時資料已經成功傳輸到客戶端了。
優缺點:

JSONP 的優點是:它不像XMLHttpRequest物件實現的Ajax請求那樣受到同源策略的限制;它的相容性更好,在更加古老的瀏覽器中都可以執行。

JSONP 的缺點是:它只支援 GET 請求,而不支援 POST 請求等其他型別的 HTTP 請求

CORS

跨源資源共享 Cross-Origin Resource Sharing(CORS) 是一個新的 W3C 標準,它新增的一組HTTP首部欄位,允許服務端其宣告哪些源站有許可權訪問哪些資源。換言之,它允許瀏覽器向聲明瞭 CORS 的跨域伺服器,發出 XMLHttpReuest 請求,從而克服 Ajax 只能同源使用的限制。

​ 另外,規範也要求對於非簡單請求,瀏覽器必須首先使用 OPTION 方法發起一個預檢請求(preflight request),從而獲知服務端是否允許該跨域請求,在伺服器確定允許後,才發起實際的HTTP請求。對於簡單請求、非簡單請求以及預檢請求的詳細資料可以閱讀HTTP訪問控制(CORS)

與 JSONP 的比較
  • JSONP 只能實現 GET 請求,而 CORS 支援所有型別的 HTTP 請求
  • 使用 CORS ,開發者可以是使用普通的 XMLHttpRequest 發起請求和獲取資料,比起 JSONP 有更好的錯誤處理
  • 雖然絕大多數現代的瀏覽器都已經支援 CORS,但是 CORS 的相容性比不上 JSONP,一些比較老的瀏覽器只支援 JSONP

Django 中如何解決跨域請求

安裝django-cors-headers
pip install django-cors-headers

註冊應用

INSTALLED_APPS = (
...
'corsheaders',
...
)

中間層設定

MIDDLEWARE = [  
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
]

新增白名單

# CORS 設定跨域域名
CORS_ORIGIN_WHITELIST = (
'127.0.0.1:8080',
'localhost:8080',
'www.xxxx.com:8080',
'api.xxxx.com:8000'
)
CORS_ALLOW_CREDENTIALS = True # 允許攜帶cookieALLOWED_HOSTS = ['www.xxxx.com:8080','api.xxxx.com:8000','127.0.0.1']# 前端需要攜帶cookies訪問後端時,需要設定withCredentials: true

設定允許訪問的方法

CORS_ALLOW_METHODS = (
'GET',
'POST',
'PUT',
'PATCH',
'DELETE',
'OPTIONS'
)

設定允許的header

CORS_ALLOW_HEADERS = (
'x-requested-with',
'content-type',
'accept',
'origin',
'authorization',
'x-csrftoken'
)