因爲瀏覽器存在同源策略,同源策略指:瀏覽器 對不一樣源的腳本或文本的訪問方式 進行的限制。好比源a的js不能讀取或設置引入的源b的元素屬性。html
(阻止從一個源 加載文檔 或腳本獲取 或設置 另外一個源 加載的文檔的屬性)。python
定義同源:就是指兩個頁面具備相同的協議,主機(也常說域名),端口,三個要素缺一不可。jquery
因爲同源策略是瀏覽器的限制,因此請求的發送和響應是 能夠進行,只不過瀏覽器不接受而已。ajax
瀏覽器的同源策略並非對全部的請求都制約:json
制約:XmlHttpRequest跨域
容許:img,script 等具備 src屬性的標籤瀏覽器
跨域名訪問,如: http://www.c1.com域名 向 http://www.c2.com域名發送請求。服務器
1.JSONP實現跨域請求app
JSONP(JSONP - JSONP with Padding 是JSON的一種 ‘使用模式’),利用script標籤的src屬性(瀏覽器容許script標籤跨域)cors
遠程:
views.py
def get_data(request): import time time.sleep(3) func_name = request.GET.get('callback') return HttpResponse('%s("機密數據123")'%func_name)
本地:
views.py
def index(request): return render(request,'index.html')
index.html
<body> <h1>江山如此多嬌</h1> <div id="i1"></div> <input type="button" onclick="jsonp('http://127.0.0.1:8001/get_data.html?callback=funcvv')" value="發送JSONP請求"/> <input type="button" onclick="Jsonp2()" value="發送JSONP2請求"> <input type="button" onclick="Jsonp3()" value="發送JSONP3請求"> <script src="/static/jquery-3.2.1.js"></script> <script> /* 手動實現jsonp */ function funcvv(arg) { alert(arg); } function jsonp(url) { tag = document.createElement('script'); tag.src = url; document.head.appendChild(tag); } function Jsonp2() { $.ajax({ url:'http://127.0.0.1:8001/get_data.html', type:'GET', dataType:'JSONP', success:function (data) { console.log(data); } }) } function list(arg) { console.log(arg); } function Jsonp3(){ $.ajax({ url: "http://127.0.0.1:8001/get_data.html", type: 'GET', dataType: 'JSONP', jsonp: 'callback', jsonpCallback: 'list' }) } </script> </body>
筆記:
- JSONP: 本地:先定義函數 遠程:func("數據") 方式一:手動 /* function funcvvvvvv(arg) { alert(arg); document.head.removeChild(tag); } function jsonp(url){ tag = document.createElement('script'); tag.src = url; document.head.appendChild(tag); }*/ 方式二:調用jQuery function Jsonp2(){ $.ajax({ url: "http://127.0.0.1:8000/get_data.html", type: 'GET', dataType: 'JSONP', success: function(data){ console.log(data); } }) } 本質:建立script標籤 編寫跨域請求: 本地: function list666(arg){ } $.ajax({ url: "http://www.jxntv.cn/data/jmd-jxtv2.html", type: 'GET', dataType: 'JSONP', jsonp: 'callback', jsonpCallback: 'list666' }) 遠程: func_name = request.GET.get('callback') return HttpResponse('%s("機密數據")' %func_name)
2.CORS
如今瀏覽器能夠支持主動設置從而容許跨域請求,即:跨域資源共享(CORS,Cross-Origin Resource Sharing),其本質是設置響應頭,是的瀏覽器容許跨域請求。
解決方法:
-------遠程 def cors_data(request): response = HttpResponse('機密數據333') # response['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8000' #設置某個能訪問的域名 response['Access-Control-Allow-Origin'] = '*' #全部 return response --------本地 views.py def index_cors(request): return render(request,'index_cors.html') .HTML <body> <h1>大浪淘沙</h1> <script src="/static/jquery-3.2.1.js"></script> <script> $.ajax({ url:'http://127.0.0.1:8001/cors_data.html', type:'GET', success:function (data) { console.log(data); } }) </script> </body>
從而引出:
*簡單請求 OR 非簡單請求 條件: 一、請求方式:HEAD、GET、POST 二、請求頭信息: Accept Accept-Language Content-Language Last-Event-ID Content-Type 對應的值是如下三個中的任意一個 application/x-www-form-urlencoded multipart/form-data text/plain 注意:同時知足以上兩個條件時,則是簡單請求,不然爲複雜請求 *簡單請求和非簡單請求的區別? 簡單請求:一次請求 非簡單請求:兩次請求,在發送數據以前會先發一次請求用於作「預檢」,只有「預檢」經過後纔再發送一次請求用於數據傳輸。 * 關於「預檢」 - 請求方式:OPTIONS - 「預檢」其實作檢查,檢查若是經過則容許傳輸數據,檢查不經過則再也不發送真正想要發送的消息 - 如何「預檢」 => 若是複雜請求是PUT等請求,則服務端須要設置容許某請求,不然「預檢」不經過 Access-Control-Request-Method => 若是複雜請求設置了請求頭,則服務端須要設置容許某請求頭,不然「預檢」不經過 Access-Control-Request-Headers
PUT方法請求(非簡單):
----遠程 def cors_data(request): if request.method == 'OPTIONS': #預檢 response = HttpResponse() #可爲空 response['Access-Control-Allow-Origin'] = '*' response['Access-Control-Allow-Methods'] = 'PUT' return response elif request.method == 'PUT': response = HttpResponse('機密數據333') # response['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8000' #設置某個能訪問的域名 response['Access-Control-Allow-Origin'] = '*' #全部 return response -------本地 def index_cors(request): return render(request,'index_cors.html') <body> <h1>大浪淘沙</h1> <script src="/static/jquery-3.2.1.js"></script> <script> $.ajax({ url:'http://127.0.0.1:8001/cors_data.html', type:'PUT', #------PUT------ success:function (data) { console.log(data); } }) </script>
GET + 自定義headers(非簡單):
--------遠程 def cors_data(request): if request.method == 'OPTIONS': #預檢 response = HttpResponse() #可爲空 response['Access-Control-Allow-Origin'] = '*' # response['Access-Control-Allow-Methods'] = 'PUT' response['Access-Control-Allow-Headers'] = 'xxx' # 自定義的 headers:{'xxx':333}, return response elif request.method == 'GET': response = HttpResponse('機密數據333') # response['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8000' #設置某個能訪問的域名 response['Access-Control-Allow-Origin'] = '*' #全部 return response -------本地 def index_cors(request): return render(request,'index_cors.html') .HTML <body> <h1>大浪淘沙</h1> <script src="/static/jquery-3.2.1.js"></script> <script> $.ajax({ url:'http://127.0.0.1:8001/cors_data.html', type:'GET', headers:{'xxx':333}, success:function (data) { console.log(data); } }) </script> </body>
#補充:
JSONP:具備兼容性
CORS(早期有些瀏覽器版本,不支持)
不到不得已,才讓發 非簡單請求(會增長服務器壓力)
例如:
筆記:
本地:無做爲 遠程:設置響應頭 response['Access-Control-Allow-Origin'] = "http://127.0.0.1:8888" response['Access-Control-Allow-Methods'] = "PUT" response['Access-Control-Allow-Headers'] = "xxx"