1.同源策略又名同域策略,就是(主機名+協議+端口號【若存在】)三者相同。也就是說javascript只能夠操做本身域下的東西,不能操做其餘域下的東西。好比百度下javascript是不可操做谷歌下的頁面;javascript
在瀏覽器中,<script>、<img>、<iframe>、<link>等標籤均可以加載跨域資源,而不受同源限制,但瀏覽器限制了JavaScript的權限使其不能讀、寫加載的內容。css
同源策略只對網頁的HTML文檔作了限制,對加載的其餘靜態資源如javascript、css、圖片等仍然認爲屬於同源。html
2.使用ajax必須知足同源策略;在本地hosts文件配置兩個域名訪問IP做爲測試用java
127.0.0.1 www.fwd.com
127.0.0.1 www.khd.compython
在 http://www.khd.com:8002/khd 文件裏用ajax請求http://www.fwd.com:8001/fwd(jquery)jquery
請求頁面(jquery):web
<input type="button" value="提交" onclick="doajax();"/>
<script>
function doajax() {
$.ajax({
url: 'http://www.fwd.com:8001/fwd',
type: 'POST',
data:{'k1':'v1'},
success: function (responseText, statusText) {
},
error: function (event, errorText, errorType) {
}
});
}
</script>
此時點擊按鈕發起ajax請求後,能夠看到請求已被瀏覽器的同源策略阻止。
3. 突破瀏覽器同源策略ajax跨域請求,有兩個辦法:ajax
法1、JSONP方式json
自定義JSONP跨域請求數據只能是get方法的請求,也就是利用script標籤和script標籤的src發送get請求跨域
1在要請求數據的頁面用js建立一個script標籤,src等於要請求數據的地址
2響應頁面返回的必須是一個帶有參數的函數名稱
3自定義對應響應頁面返回的函數,這樣自定義的函數也就會執行了,就能獲得數據
請求頁面(原生js):
<input type="button" value="跨域提交" onclick="doajax();"/> <script> //利用原生js本身建立一個跨域請求 function doajax() { //當點擊提交按鈕是執行函數 var tag = document.createElement('script'); //建立一個script標籤 tag.src = 'http://www.fwd.com:8001/fwd'; //設置script標籤的src地址,爲要請求數據的地址,由於src是不受同源策略 document.head.appendChild(tag); //將script標籤添加到head標籤裏面 document.head.removeChild(tag); //添加後會當即發送請求,因此這裏能夠將添加的script標籤刪除了 } //響應網站返回,shuju({'k1':'v1'}); 也就至關於返回了一個帶有參數的函數名稱 function shuju(shj) { //自定義執行函數,和響應網站返回的名稱相同,參數就是響應網站返回的數據 for(var i in shj){ //循環響應網站返回的數據 alert(i + ':' + shj[i]); //打印出數據的鍵和值,v1:k1 } } </script>
響應頁面:
class fwdHandler(tornado.web.RequestHandler):
def get(self): #接收get請求
# self.render("fwd.html")
self.write("shuju({'k1':'v1'});") #返回的數據
def post(self):
self.write("post請求成功")
ajax的JSONP方式:
ajax跨域請求本質上就是上面自定義跨域的方式,只不過ajax幫咱們封裝好了,不用咱們去建立script標籤
請求頁面(jquery):
<input type="button" value="跨域提交" onclick="doajax();"/> <script> function doajax() { //當點擊提交按鈕是執行函數 $.ajax({ type: 'GET', url: 'http://www.fwd.com:8001/fwd', dataType: 'jsonp', //JSONP,數據類型 jsonpCallBack:'shj' //接收響應頁面帶有參數的函數名稱,shj來自響應端 }); } //響應網站返回,shuju({'k1':'v1'}); 也就至關於返回了一個帶有參數的函數名稱 function shuju(shj) { //自定義執行函數,和響應網站返回的名稱相同,也就會執行自定義函數,而參數就是響應網站返回的數據 for (var i in shj) { //循環響應網站返回的數據 alert(i + ':' + shj[i]); //打印出數據的鍵和值 } } </script>
響應端:
class fwdHandler(tornado.web.RequestHandler): def get(self): #接收get請求 # self.render("fwd.html") self.write("shuju({'k1':'v1'});") #返回數據 def post(self): self.write("post請求成功")
法2、基於CORS實現跨域Ajax
請求頁面不變,響應端返回數據的時候帶有響應頭標識,告訴瀏覽器容許跨域請求。
響應端:
class fwdHandler(tornado.web.RequestHandler):
def get(self): #接收get請求
pass
def post(self):
self.set_header('Access-Control-Allow-Origin','*')
self.write("{'k1':'v1'}") # 返回數據
跨域傳輸cookie(跨域請求中,默認HTTP Authentication信息,Cookie頭以及用戶的SSL證書都是不會被髮送):
請求頁面(jquery):
xhrFields:{withCredentials: true}, //傳遞Cookie頭以及用戶的SSL證書
響應端(python):
class fwdHandler(tornado.web.RequestHandler): def get(self): #接收get請求 pass def options(self): #接收預檢的options請求 self.set_header('Access-Control-Allow-Credentials', "true") #傳遞Cookie頭以及用戶的SSL證書 self.set_header('Access-Control-Allow-Origin', 'http://www.khd.com:8002') #預檢請求或者數據請求時容許跨域,容許跨域的域名 self.set_header('Access-Control-Allow-Methods', 'PUT') #預檢請求時容許請求頁面的請求方式跨域,容許跨域的請求方式(多個逗號隔開) self.set_header('Access-Control-Allow-Headers', "k1,k2") #預檢請求時容許請求頁面ajax設置請求頭headers屬性跨域,容許跨域的headers屬性請求頭(多個逗號隔開) def put(self): self.set_header('Access-Control-Allow-Credentials', "true") # 傳遞Cookie頭以及用戶的SSL證書 self.set_header('Access-Control-Allow-Origin','http://www.khd.com:8002') self.write("{'k1':'v1'}") # 返回數據 self.set_cookie('kkkkk', 'vvvvv') #寫入cookie print(self.get_cookie('kkkkk')) #獲取cookie