同源策略與Jsonp

同源策略與Jsonp

同源策略

同源策略(Same origin policy)是一種約定,它是瀏覽器最核心也最基本的安全功能,若是缺乏了同源策略,則瀏覽器的正常功能可能都會受到影響。能夠說Web是構建在同源策略基礎之上的,瀏覽器只是針對同源策略的一種實現。javascript

同源策略,它是由Netscape提出的一個著名的安全策略。如今全部支持JavaScript 的瀏覽器都會使用這個策略。所謂 同源是指,域名,協議,端口相同。當一個瀏覽器的兩個tab頁中分別打開來 百度和谷歌的頁面當瀏覽器的百度tab頁執行一個腳本的時候會檢查這個腳本是屬於哪一個頁面的,即檢查是否同源,只有和百度同源的腳本纔會被執行。 若是非同源,那麼在請求數據時,瀏覽器會在控制檯中報一個異常,提示拒絕訪問。
 

示例:非同源請求報錯(項目端口不一樣)

項目1:
 
setting.py 配置靜態文件
STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

 靜態文件: html


<script src="http://code.jquery.com/jquery-latest.js"></script>前端

urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'index/$',views.index),
    url(r'ajax_send/$',views.ajax_send),
]

  

 
views.py
from django.shortcuts import render,HttpResponse

def index(request):
    return render(request,"index.html")


def ajax_send(request):
   print('項目1...............') return HttpResponse("項目1的數據")

  

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
<h3>pro1的首頁</h3>

<button class="b1">send a request</button>
</body>
<script src="/static/jquery.js"></script>
<script>
    $(".b1").click(function(){
        $.ajax({
            //url:"/ajax_send/", //訪問項目1的本路徑
            url:"http://127.0.0.1:8080/ajax_send/", //訪問項目2的路徑,同源策略接收不到數據。
            success:function(data){
                alert(data);
            }
        })
    })

</script>
</html>

  

項目2的代碼同上java

//===================================setting.py


STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR,'static'),
)


//===================================urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'index/$',views.index),
    url(r'ajax_send/$',views.ajax_send),
]


//===================================views.py

from django.shortcuts import render,HttpResponse

def index(request):
    return render(request,"index.html")


def ajax_send(request):
   print('項目2..............') return HttpResponse("項目2的數據") //===================================index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>index</title> </head> <body> <h3>pro2的首頁</h3> <button class="b2">send a request</button> </body> <script src="/static/jquery.js"></script> <script> $(".b2").click(function(){ $.ajax({ url:"/ajax_send/", success:function(data){ alert(data); } }) }) </script> </html>

  

同源問題: 當點擊項目1的按鈕時,發送了請求,可是會發現報錯以下:python

已攔截跨源請求:同源策略禁止讀取位於 http://127.0.0.1:7766/SendAjax/ 的遠程資源。(緣由:CORS 頭缺乏 'Access-Control-Allow-Origin')。

可是注意,項目2中的訪問已經發生了,說明是瀏覽器對非同源請求返回的結果作了攔截。jquery

 

注意:jquery.js也是非同源請求,但卻能拿到數據。script標籤請求不攔截,就攔截ajax請求。

 

script標籤請求:

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
<h3>pro1的首頁</h3>

<button class="b1">send a request</button>
</body>
<script src="/static/jquery.js"></script>
<script>
    /*
    $(".b1").click(function(){
        $.ajax({
            //url:"/ajax_send/", //訪問項目1的本路徑
            url:"http://127.0.0.1:8080/ajax_send/", //訪問項目2的路徑
            success:function(data){
                alert(data);
            }
        })
    })
    */
</script>
<!-- 單發一個script請求。刷新頁面則請求。-->
<script src="http://127.0.0.1:8080/ajax_send/"></script>

</html>

  

刷新頁面:ajax

 項目2的返回值改爲英文。定義成一個變量。django

from django.shortcuts import render,HttpResponse

def index(request):
    return render(request,"index.html")


def ajax_send(request):
    print('項目2.........')
    # return HttpResponse("項目2的數據")
    return HttpResponse("baobao")

 

項目1的js中定義baobao這個變量。運行結果:頁面不會報錯了。json

<script>
  var baobao="貝貝";
</script>
<!-- 單發一個script請求。刷新頁面則請求。-->
<script src="http://127.0.0.1:8080/ajax_send/"></script>

  

運行結果:頁面不會報錯了。跨域

 

 定義一個變量是沒有意義的。接下來項目1的js中定義一個函數。

項目1的js中定義一個函數:

<script>
    // 定義函數
    function baobao(){
        console.log('貝貝');
    }
    // baobao();  //調用函數
</script>
<!-- 單發一個script請求。刷新頁面則請求。-->
<script src="http://127.0.0.1:8080/ajax_send/"></script>

 

項目2返回的值是一個調用函數的字符串。至關於調用了項目1裏的函數。

def ajax_send(request):
    print('項目2.........')
    # return HttpResponse("項目2的數據")
    # return HttpResponse("baobao")
    return HttpResponse("baobao()")

 刷新項目1的頁面,運行結果以下:

 

本質項目1想拿項目2的數據。

項目2實參上傳些值給項目1.

def ajax_send(request):
    print('項目2.........')
    # return HttpResponse("項目2的數據")
    # return HttpResponse("baobao")
    # return HttpResponse("baobao()")
    return HttpResponse("baobao('項目2的數據')")

 項目1接收傳參:

<script>
    function baobao(s){
        console.log(s);
    }
    // baobao('項目2的數據');  //調用函數
</script>
<!-- 單發一個script請求。刷新頁面則請求。-->
<script src="http://127.0.0.1:8080/ajax_send/"></script>

  

運行結果:

 

假設項目2不發送字符串,而是發送字典類型的數據給項目1。項目1該如何接收???

項目2:序列化字典:json.dumps(res)

def ajax_send(request):
    print('項目2.........')
    # return HttpResponse("項目2的數據")
    # return HttpResponse("baobao")
    # return HttpResponse("baobao()")
    # return HttpResponse("baobao('項目2的數據')")

    res={"name":"寶寶"}
    import json
    return HttpResponse("baobao('%s')"%json.dumps(res))

 

項目1:反序列化數據:JSON.parse(s);    JSONP的來歷!!!!

<script>   
    // 接收傳參
    // 定義函數
    function baobao(s){
        console.log(s);
        JSON.parse(s);
    }
    // baobao('項目2的數據');  //調用函數
</script>
<!-- 單發一個script請求。刷新頁面則請求。-->
<script src="http://127.0.0.1:8080/ajax_send/"></script>

  

項目1刷新頁面:運行結果:

 

 接下來動態定義函數名!!!

 項目1傳的的是什麼函數名,項目2就是動態的函數名。

 項目1:

<script>
    // 定義函數
    function foo(s){
        console.log(s);
        JSON.parse(s);
    }
</script>
<!-- 項目1傳的的是什麼函數名,項目2就是動態的函數名。-->
<script src="http://127.0.0.1:8080/ajax_send/?a=foo"></script>

項目2:


def ajax_send(request):
    print('項目2.........')

    func = request.GET.get("a")
    res={"name":"寶寶"} import json return HttpResponse("%s('%s')"%(func,json.dumps(res))) 

  

運行結果:

 思考:以上都是刷新頁面發送請求的,如何點擊按鈕發送請求呢???

項目1中新增一個按鈕,點擊b2發送請求。

 項目1的index.html:

<button class="b2">send a request_b2</button>
<script>
    // 思考:以上都是刷新頁面發送請求的,如何點擊按鈕發送請求呢???
    $(".b2").click(function(){
        // 建立一個script標籤,添加到body中。
        var $ele_script = $("<script>");
        $ele_script.attr("src","http://127.0.0.1:8080/ajax_send/?a=foo");
        $("body").append($ele_script);
    })
</script>

  

運行結果:

 

 項目1:封裝功能代碼:把路徑當成參數動態傳值。而且清空該標籤。

 項目1:index.html

    // 定義函數
    function foo(s){
        console.log(s);
        JSON.parse(s);
    }

    // 封裝功能代碼:把路徑當成參數動態傳值。
    function kuayu(url){
        // 建立一個script標籤,添加到body中。
        var $ele_script = $("<script>");
        $ele_script.attr("src",url);
        $ele_script.attr("class","kuayu");
        $("body").append($ele_script); //發送請求
        // 請求完成以後刪除該標籤
        $(".kuayu").remove()
    };

    $(".b2").click(function(){
        kuayu("http://127.0.0.1:8080/ajax_send/?a=foo")
    });

  

基於jqeury的API實現跨越請求

 //====================基於jqeury的API實現跨越請求====================

對script請求的封裝

 項目1:

//====================基於jqeury的API實現跨越請求====================
$(".b2").click(function(){
    // 跨域請求
    $.getJSON("http://127.0.0.1:8080/ajax_send/?a=?",function(data){
        console.log(data);
    });
});  

 

a是一個隨機字符串的函數名。

項目2:

def ajax_send(request):
    print('項目2.........')

    func = request.GET.get("a")
    print("func",func)
    res={"name":"寶寶"}
    import json
    return HttpResponse("%s('%s')"%(func,json.dumps(res)))

 

項目2運行結果:

 

 

結果是同樣的,要注意的是在url的後面必須添加一個callback參數,這樣getJSON方法纔會知道是用JSONP方式去訪問服務,callback後面的那個問號是內部自動生成的一個回調函數名。

      此外,若是說咱們想指定本身的回調函數名,或者說服務上規定了固定回調函數名該怎麼辦呢?咱們可使用$.ajax方法來實現

 $.ajax

//====================基於jqeury的API(ajax)實現跨越請求====================

 項目1:

//====================基於jqeury的API(ajax)實現跨越請求====================
    function baobao(s){
        console.log(s);
    }

    $(".b2").click(function(){
        $.ajax({
            url:'http://127.0.0.1:8080/ajax_send/',
            //url:'http://127.0.0.1:8080/ajax_send/?a=baobao',  至關於
            dataType:'jsonp',  // 期待數據類型.會生成script標籤請求。
            jsonp: 'a', // 鍵
            jsonpCallback:"baobao" // 值
        })

    });

  

項目1運行結果:

項目2運行結果:

 

 

//====================以上代碼仍是要自定義函數,接下來終極版!!!====================

 項目1:

//====================以上代碼仍是要自定義函數,接下來終極版!!!====================

    $(".b2").click(function(){
        $.ajax({
            url:'http://127.0.0.1:8080/ajax_send/',
            //url:'http://127.0.0.1:8080/ajax_send/?a=隨機字符串',
            dataType:'jsonp',  // 期待數據類型.會生成script標籤請求。
            jsonp: 'a', //鍵
            success:function(data){
          console.log(data); }
        })

    });

  

項目2的運行結果:

 

應用:

// =========================================================================================
    // 應用
    $(".b2").click(function(){
        $.ajax({
            url:'http://www.jxntv.cn/data/jmd-jxtv2.html?',
            dataType:'jsonp',  // 期待數據類型.會生成script標籤請求。
            jsonp: 'callback', //鍵
            jsonCallback:"list"
        });

    });

    function list(data){
        //console.log(data.data);
        $.each(data.data,function(i,weekday){
            //console.log(weekday); // {week: "週日", list: Array(19)}
            $("body").append("<p>"+ weekday.week +"</p>");
            //console.log(weekday.list); // {19個數據}  0:{time: "0030", name: "通宵劇場六集連播", link: "http://www.jxntv.cn/live/jxtv2.shtml"}
            $.each(weekday.list,function(j,show){
                s="<p><a href='+ show.link +'>"+ show.name +"</a><p>"
                $("body").append(s);
            })

        });
    };

  

運行結果:

 

總結:

jsonp是json用來跨域的一個東西。原理是經過script標籤的跨域特性來繞過同源策略。

 

JSONP的原型建立一個回調函數,而後在遠程服務上調用這個函數而且將JSON 數據形式做爲參數傳遞,完成回調。

 

 將JSON數據填充進回調函數,這就是JSONP的JSON+Padding的含義。

 

jQuery框架也固然支持JSONP,可使用$.getJSON(url,[data],[callback])方法

<script>

    function f(){

            $.ajax({
               url:"http://127.0.0.1:7766/SendAjax/",
               dataType:"jsonp",            //必須有,告訴server,此次訪問要的是一個jsonp的結果。
               jsonp: 'callbacks',          //jQuery幫助隨機生成的:callbacks="wner"
               success:function(data){
                   alert("hi "+data)
              }
         });

       }

</script>

  

  jsonp: 'callbacks'就是定義一個存放回調函數的鍵,jsonpCallback是前端定義好的回調函數方法名'SayHi',server端接受callback鍵對應值後就能夠在其中填充數據打包返回了; 

 jsonpCallback參數能夠不定義,jquery會自動定義一個隨機名發過去,那前端就得用回調函數來處理對應數據了。利用jQuery能夠很方便的實現JSONP來進行跨域訪問。  

 注意 JSONP必定是GET請求

相關文章
相關標籤/搜索