天天看點

Django前後端分離2——CORS跨域

一.CORS

1.同源政策

如果兩個頁面的協定,域名和端口完全一緻,則兩個頁面同源。

同源政策是浏覽器的一個安全功能,不同源的用戶端腳本(ajax)在沒有明确授權的情況下,不能讀寫對方資源。

2.CORS概念

CORS是一個W3C标準,全稱是"跨域資源共享"(Cross-origin resource sharing),是跨域問題的解決方案之一。它允許浏覽器向跨源伺服器,發出XMLHttpRequest請求,進而克服了AJAX隻能同源使用的限制。

3.CORS特點

  1. 浏覽器自動完成(在請求頭中加入特殊頭 或 發送特殊請求)
  2. 伺服器需要支援(響應頭中需要有特殊頭)

4.跨域請求類型

  1. 簡單請求
  • 請求方法如下:GET or HEAD or POST
  • 請求頭僅包含:Accept,Accept-Language,Content-Language,Content-Type
  • Content-Type 僅支援如下三種:application/x-www-form-urlencoded,multipart/form-data,ext/plain

2.預檢請求:不滿足以上任意一點的請求都是 預檢請求

前後端分離時通過json傳輸資料,是以content_type必然不滿足簡單請求的要求(application/json),是以均為預檢請求

5.跨域請求流程

  1. 簡單請求流程

    請求頭中 攜帶 Origin,該字段表明自己來自哪個域

    如果請求頭中的Origin在伺服器接受範圍内, 則傳回如下頭:

    如果伺服器不接受此域,則響應頭中不包含 Access-Control-Allow-Origin

響應頭 作用 備注
Access-Control-Allow-Origin 伺服器接受的域
Access-Control-Allow-Credentials 是否接受跨域的Cooike 可選
Access-Control-Expose-Headers 預設情況下,xhr隻能拿到如下響應頭:Cache-Control,Content-Language,Content-Type,Expires,Last-Modified;如果有需要擷取其他頭,需在此指定 可選
  1. 預檢請求流程:使用設定的請求方式請求資料之前,先發送一個OPTIONS請求,看服務端是否允許用戶端發送非簡單請求,隻有"預檢"通過後才會再發送一次請求用于資料傳輸
  • OPTION 請求發起,攜帶如下請求頭
請求頭 作用 備注
Origin 表明此請求來自哪個域 必選
Access-Control-Request-Method 此次請求使用方法 必選
Access-Control-Request-Headers 此次請求使用的頭 必選
  • OPTION 接受響應階段,攜帶如下響應頭
響應頭 作用 備注
Access-Control-Allow-Origin 同簡單請求 必選
Access-Control-Allow-Methods 告訴浏覽器,伺服器接受得跨域請求方法 必選
Access-Control-Allow-Headers

傳回所有支援的頭部,當request有

‘Access-Control-Request-Headers’時,該響應頭必然回複

必選
Access-Control-Allow-Credentials 同簡單請求 可選
Access-Control-Max-Age

OPTION請求緩存時間,機關s

每次預檢請求都會發送OPTION和post兩個請求,此設定可緩解伺服器壓力

可選
  • 主請求階段
請求頭 作用 備注
Origin 表明此請求來自哪個域
  • 主請求響應階段
響應頭 作用 備注
Access-Control-Allow-Origin 目前伺服器接受得域

二.django對CORS的支援

pip install django-cors-headers

settings.py中增加如下配置

1,INSTALLED_APPS 中添加 corsheaders
2,MIDDLEWARE 中添加 corsheaders.middleware.CorsMiddleware
     位置盡量靠前,官方建議放在 ‘django.middleware.common.CommonMiddleware’ 上方
     禁掉csrf中間件
3,CORS_ORIGIN_ALLOW_ALL  布爾值  如果為True,所有域均可通路 白名單不啟用
4,CORS_ORIGIN_WHITELIST =[
		"https://example.com"
	]
5, CORS_ALLOW_METHODS = (
			'DELETE',
			'GET',
			'OPTIONS',
			'PATCH',
			'POST',
			'PUT',
			)
6, CORS_ALLOW_HEADERS = (
			'accept-encoding',
			'authorization',  # 這個裡面放token
			'content-type',
			'dnt',
			'origin',
			'user-agent',
			'x-csrftoken',
			'x-requested-with',
		)
7, CORS_PREFLIGHT_MAX_AGE  浏覽器或者用戶端可以緩存預檢響應的秒數,
	如果是0或者任何假值,則再次發送請求時,還需要進行預檢,預設是86400(一天)
8, CORS_EXPOSE_HEADERS  []  擴充的請求頭,預設為空
9, CORS_ALLOW_CREDENTIALS  是否接收cookie,布爾值, 預設False