同源策略以及跨域訪問

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
相關文章
相關標籤/搜索