一. jsonp解決跨域問題
1. 函數中傳參
dom1中的HTML
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>xyz</title> </head> <body> <button id="b1">點我</button> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script> function rion(res) { console.log(res); } </script> <script src="http://127.0.0.1:8002/abc/"></script> </body> </html>
demo2 中的視圖函數:
def abc(request):
res = {"code": 0, "data": ["SNIS-561", "SNIS-517", "SNIS-539"]}
return HttpResponse("rion({})".format(json.dumps(res)))
JQuery中getJSON方法:
demo2中HTML
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>xyz</title> </head> <body> <button id="b1">點我</button> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script> $("#b1").click(function () { $.getJSON("http://127.0.0.1:8002/abc/?callback=?", function (res) { console.log(res); }) }); </script> </body> </html>
要注意的是在url的后面必須要有一個callback參數,這樣getJSON方法才會知道是用JSONP方式去訪問服務,callback后面的那個?是jQuery內部自動生成的一個回調函數名。
二. CORS解決跨域問題
CORS是一個W3C標准,全稱是"跨域資源共享"(Cross-origin resource sharing)。它允許瀏覽器向跨源服務器發出XMLHttpRequest請求,從而解決AJAX只能同源使用的限制.
瀏覽器將CORS請求分為兩類: 簡單請求和非簡單請求
一個請求需要同時滿足 以下兩大條件 才屬於簡單請求.
(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
簡單請求的處理方式
在跨域場景下,當瀏覽器發送簡單請求時,瀏覽器會自動在請求頭中添加表明請求來源的 Origin 字段。

我們的后端程序只需要在返回的響應頭中加上 Access-Control-Allow-Origin 字段,並且把該字段的值設置為 跨域請求的來源地址或簡單的設置為 * 就可以了。
例如:我們可以在Django中間件中的process_response方法來給相應對象添加該字段。
from django.utils.deprecation import MiddlewareMixin
class CorsMiddleware(MiddlewareMixin):
def process_response(self, request, response):
# 給響應頭加上 Access-Control-Allow-Origin 字段 並簡單的設置為 *
response['Access-Control-Allow-Origin'] = '*'
return response
非簡單請求的處理方式 >>
我們開發中常用到的那些請求方法是PUT或DELETE,或者Content-Type字段的類型是application/json的都是非簡單請求。
對於非簡單請求,瀏覽器通常都會在請求之前發送一次 OPTIONS 預檢 請求。該請求會像后端服務詢問是否允許從當前源發送請求並且詢問允許的 請求方法 和 請求頭字段。

解決方案在上面Django的中間件中添加如下代碼:
from django.utils.deprecation import MiddlewareMixin
class CorsMiddleware(MiddlewareMixin):
def process_response(self, request, response):
# 給響應頭加上 Access-Control-Allow-Origin 字段 並簡單的設置為 *
response['Access-Control-Allow-Origin'] = '*'
if request.method == 'OPTIONS':
# 允許發送 PUT 請求
response['Access-Control-Allow-Methods'] = 'PUT, DELETE'
# 允許在請求頭中攜帶 Content-type字段,從而支持發送json數據
response['Access-Control-Allow-Headers'] = 'Content-type'
return response
三. 使用 Django-corset-headers 解決跨域問題
我們這個中間件確實能解決目前的CORS跨域問題,但是我們的土方法肯定是不夠嚴謹的,已經有人造好輪子-- django-cors-headers 了。
我們只需要安裝這個包,然后按需要配置一下就可以了。
安裝
pip install django-cors-headers
注冊APP
INSTALLED_APPS = [
...
'app01.apps.App01Config',
'corsheaders', # 將 corsheaders 這個APP注冊
]
添加中間件
必須放在最前面,因為要先解決跨域的問題。只有允許跨域請求,后續的中間件才會正常執行。
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # 添加中間件
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
配置
你可以選擇不限制跨域訪問
CORS_ORIGIN_ALLOW_ALL = True
或者你可以選擇設置允許訪問的白名單
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
# '<YOUR_DOMAIN>[:PORT]',
'127.0.0.1:8080'
)
更多詳細配置詳細請查看django-cors-headers項目

