URL | 結果 | 緣由 |
---|---|---|
http://a.xyz.com/dir2/other.html |
成功 | |
http://a.xyz.com/dir/inner/another.html |
成功 | |
https://a.xyz.com/secure.html |
失敗 | 不一樣協議 ( https和http ) |
http://a.xyz.com:81/dir/etc.html |
失敗 | 不一樣端口 ( 81和80) |
http://a.opq.com/dir/other.html |
失敗 | 不一樣域名 ( xyz和opq) |
<!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); } function addScriptTag(src) { var scriptEle = document.createElement("script"); $(scriptEle).attr("src", src); $("body").append(scriptEle); $(scriptEle).remove(); } $("#b1").click(function () { addScriptTag("http://127.0.0.1:8002/abc/?callback=rion") }); </script> </body> </html>
def abc(request): res = {"code": 0, "data": ["SNIS-561", "SNIS-517", "SNIS-539"]} func = request.GET.get("callback") return HttpResponse("{}({})".format(func, json.dumps(res)))
<!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); }) }); //要注意的是在url的後面必需要有一個callback參數,這樣getJSON方法纔會知道是用JSONP方式去訪問服務, // callback後面的那個?是jQuery內部自動生成的一個回調函數名。 </script> </body> </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 () { $.ajax({ url: "http://127.0.0.1:8002/abc/", dataType: "jsonp", jsonp: "callback", jsonpCallback: "rion2" //若是服務端規定了回調函數名,可使用$.ajax方法來實現: }) }); function rion2(res) { console.log(res); } //不過一般都會將回調函數寫在success回調中: $("#b1").click(function () { $.ajax({ url: "http://127.0.0.1:8002/abc/", dataType: "jsonp", success: function (res) { console.log(res); } }) }) </script> </body> </html>
一個請求須要同時知足如下兩大條件才屬於簡單請求。css
(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 字段。html
後端程序只須要在返回的響應頭中加上 Access-Control-Allow-Origin 字段,而且把該字段的值設置爲 跨域請求的來源地址或簡單的設置爲 * 就能夠了。jquery
例如:能夠在Django中間件中的process_response方法來給相應對象添加該字段。git
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)的支持就能夠了。github
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
上面中間件確實能解決目前的CORS跨域問題,可是不夠嚴謹,已經有人造好輪子-- django-cors-headers 了。 更多詳細配置詳細請查看django-cors-headers項目ajax
1.安裝 pip install django-cors-headers 2.註冊APP INSTALLED_APPS = [ ... 'app01.apps.App01Config', 'corsheaders', # 將 corsheaders 這個APP註冊 ] 3.添加中間件 必須放在最前面,由於要先解決跨域的問題。只有容許跨域請求,後續的中間件纔會正常執行。 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', ] 4.配置 #能夠選擇不限制跨域訪問 CORS_ORIGIN_ALLOW_ALL = True # 或者能夠選擇設置容許訪問的白名單 CORS_ORIGIN_ALLOW_ALL = False CORS_ORIGIN_WHITELIST = ( # '<YOUR_DOMAIN>[:PORT]', '127.0.0.1:8080' )