Django跨域資源共享問題小結

摘要

最近作了一個先後端分離的web項目,其中我司職後端,使用django框架。在先後端集成測試的時候,就遇到了一些web安全相關的問題,cors跨域資源共享就是其中之一。前端

cors問題介紹

跨域資源共享(CORS) 是一種機制,它使用額外的 HTTP 頭來告訴瀏覽器 讓運行在一個 origin (domain) 上的Web應用被准許訪問來自不一樣源服務器上的指定的資源。當一個資源從與該資源自己所在的服務器不一樣的域、協議或端口請求一個資源時,資源會發起一個跨域 HTTP 請求。 CORS機制容許 Web 應用服務器進行跨域訪問控制,從而使跨域數據傳輸得以安全進行。現代瀏覽器支持在API容器中使用CORS,以下降跨域 HTTP 請求所帶來的風險。web

一個域是由協議、主機和端口號組成的,簡單地說,當兩個url的協議、主機和端口中存在一個不一樣時,它們屬於不一樣域,那麼它們之間的互相訪問就會產生跨域訪問問題。django

url

個人項目中,前端的地址是http://localhost:8001,後端的地址是http://localhost:8000,兩個地址的協議和主機都相同,可是端口號不一樣,所以,前端調用後端接口時,就會產生跨域訪問的問題。後端

簡單請求

簡單請求不會觸發跨域訪問中的預檢請求,知足下列條件的爲簡單請求:跨域

  • 使用下列方法之一
    • GET
    • HEAD
    • POST
  • headers字段集合主要包含如下類型:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-type:text/plainmultipart/form-dataapplication/x-www-form-urlencoded
    • DRP
    • DownLink
    • Save-Data
    • Viewport-Width
    • Width

非簡單請求

非簡單請求即不知足簡單請求條件的請求。非簡單請求在發出請求前須要先發送一個預檢請求,請求方法爲OPTIONS方法。預檢請求的使用,能夠避免跨域請求對服務器的用戶數據產生未預期的影響。 當請求知足下述任一條件時,即應首先發送預檢請求:瀏覽器

  • 使用瞭如下的HTTP方法:
    • PUT
    • DELETE
    • CONNECT
    • OPTIONS
    • TRACE
    • PATCH
  • 首部字段裏面包含了非簡單請求的頭部字段的字段

django中遇到的問題

在後臺開發中,就遇到了這樣的狀況緩存

錯誤提示中顯示,請求被CORS協議阻攔。安全

這裏的 Origin字段說明了請求源地址,採用了 OPTIONS方法,而後發出請求的地址 Host就是本機地址。下面是服務器的響應,可是沒有發出實際請求
而後,爲了解決這一問題,我搜索事後,安裝了django-cors-headers庫,而且進行了配置,這裏配置時我把django-cors-headers中間件放在了中間件第一位。再次訪問一樣的地址,結果以下:

預檢請求

  1. 首先,瀏覽器檢測訪問的請求頭中的字段,存在對CORS安全的首部字段集合以外的字段,因此,向服務器發送一個預檢請求。上圖可見,方法爲OPTIONS,該方法不會對服務器資源產生影響。其中的請求頭中的Access-Control-Request-Method字段代表實際請求會採用GET方法,Origin表示請求源,會在服務器中接受驗證。
  2. 驗證經過後,會在response請求頭添加不一樣的字段進行返回, 字段的意思以下:
    • 首部字段Access-Control-Allow-Headers:表示服務器容許的頭部字段。
    • 首部字段Access-Control-Allow-Methods:代表服務器容許客戶端使用 POST, GETOPTIONS 等等方法發起請求。
    • 首部字段Access-Control-Allow-Origin:表示服務器容許的請求源。
    • 首部字段Access-Control-Max-Age:代表該響應的有效時間爲86400秒,也就是24 小時。在有效時間內,瀏覽器無須爲同一請求再次發起預檢請求。
  3. 而後,客戶端會發出實際請求,從結果上來看,預檢請求的response請求體中沒有任何信息,而實際請求則攜帶了服務器返回的信息。不難看出,預檢請求確實就是與服務器提早溝通,獲取與服務器相關信息的。

簡單的總結

非簡單請求須要發送預檢請求進行判斷,而後服務端與客戶端須要在頭部字段上達成一致,這樣才能正常訪問。不過,在django的開發中,直接使用django-cors-headers庫之後,只須要簡單的配置就可以很好的解決問題。服務器

存在的問題

我在測試時嘗試使用本身寫的中間件來補充頭部信息,可是在瀏覽器清除緩存後,就會致使登陸異常,而且瀏覽器沒有顯示預檢請求。等問題解決後,會把問題和解決方案再更新上來。app

參考的資料

MDN:HTTP訪問控制(CORS)
跨域——CORS詳解

若是有什麼不對之處歡迎指正!

相關文章
相關標籤/搜索