Django的跨域請求--JSONP的本質

Django的跨域請求--JSONP的本質

一般咱們在寫web端的代碼,能夠經過url得到想對應的響應數據如:html

1.urls.py
urlpatterns = [

    url(r'^get_data/', views.data),

]
2.views.py
def data(request):

    return HttpResponse("機密數據")

而對於這個「機密數據」咱們能夠經過url直接能夠獲取以下前端

也能夠經過其餘的終端獲取以下jquery

那麼如今有一個問題若是有個第三方的web端經過它的頁面想讓這段機密數據在本身的web頁面上進行顯示時如何實現:web

第一步:

新建立一個Django的web服務:ajax

一、urls.pydjango

2.views.pyjson

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

3.html後端

4.啓動web(由於同時啓動兩個Django需將對應的端口修改)跨域

如今一個web(機密數據),一個web(維基解密),如今的需求就是維基解密想將機密數據在其index的頁面進行顯示,這個如何完成???瀏覽器

這個方法有不少種:

方法1:經過後端請求:

  • views.py

    def index(request):
          response = requests.get('http://127.0.0.1:8000/get_data/').text
          return render(request,"index.html",{'response':response})
  • index.html

    {% load staticfiles %}
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
          <script src="{% static 'jquery-3.2.1.js'%}"></script>
      </head>
      <body>
      <h1>維基解密</h1>
      <b>{{ response }}</b>
    
      </body>
      </html>

渲染效果

該方法經過後臺至關於發送了兩次get請求才將數據取到

方法2:前端Ajax獲取

  • index.html

    {% load staticfiles %}
          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>Title</title>
              <script src="{% static 'jquery-3.2.1.js' %}"></script>
          </head>
          <body>
          <h1>維基解密</h1>
          <b>{{ response }}</b>
          <script>
              $.ajax({
                  url:'http://127.0.0.1:8000/get_data/',
                  type:'GET',
                  success:function(arg){
                      alert(arg)
                  }
              })
          </script>
          </body>
          </html>

可是會遇到下面這個狀況使咱們沒法獲取數據:

其實這個是咱們的瀏覽器會攔截:

具體瀏覽器從何時進行攔截的咱們能夠驗證

因此這裏能夠知道其實機密數據的數據已經發送過來只是被瀏覽器給攔截,那對於這種狀況咱們應該如何繞過攔截而獲取數據??

如何繞過瀏覽器的同源策略

1、JSONP方式

從以往的前端HTML咱們能夠知道,其實在HTML的一些標籤中有些標籤是不受同源策略的影響如:

  • img標籤

  • script 標籤

  • iframe標籤

因此經過這個點咱們能夠將代碼作修改利用這些標籤的屬性來繞過瀏覽器的同源策略:

{% load staticfiles %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="{% static 'jquery-3.2.1.js' %}"></script>
        <script src="http://127.0.0.1:8000/get_data/"></script>
    </head>
    <body>
    <h1>維基解密</h1>
    
    </body>
    </html>

這裏咱們利用script的src的屬性直接將機密數據的url放置,按理應該是能夠將數據給咱們返回的:

執行的結果以下:

上面顯示數據其實咱們已經拿到了,可是沒有渲染在頁面上,報錯提醒是該端值未定義!!

這是由於咱們使用的是script標籤將咱們取到的機密數據只是一個單純的文本格式,而script是渲染js文檔的全部顯示顯示沒有定義的變量:

咱們能夠進行驗證以下

1.現將機密數據做爲一個func的函數參數渲染

2.維基解密的index.html的html

{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="{% static 'jquery-3.2.1.js' %}"></script>
    <script>
        function func(arg){
            console.log(arg);
        }
    </script>
    <script src="http://127.0.0.1:8000/get_data/"></script>
</head>
<body>
<h1>維基解密</h1>
<b>{{ response }}</b>

</body>
</html>

這段代碼咱們先定義了func,再用script引入機密數據

3.結果

這樣咱們很好的繞開了瀏覽器的同源策略並取到數據

咱們還能夠進一步的優化代碼

views.py

index.html的html代碼

{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script src="{% static 'jquery-3.2.1.js' %}"></script>
    
</head>
<body>
<h1>維基解密</h1>
<input type="button" onclick="jsonp('http://127.0.0.1:8000/get_data?callback=funcxxx')" value="發送JSONP請求">
<script>

    function funcxxx(arg) {
        alert(arg);
    }
    function jsonp(url){
        var tag = document.createElement('script');
        tag.src = url;
        document.head.appendChild(tag);
        document.head.removeChild(tag);
    }
</script>
</body>
</html>

上述代碼就是jsonp的本質執行的過程

而在jQuery中提供了jsonp的方式:

index.html的html代碼

{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="{% static 'jquery-3.2.1.js' %}"></script>
</head>
<body>
<h1>維基解密</h1>
<input type="button" onclick="jsonp()" value="發送JSONP請求">
<script>
function jsonp(){
    $.ajax({
        url:"http://127.0.0.1:8000/get_data?callback=funcxxx",
        type:'GET',
        dataType:'JSONP',
        success:function(data){
            console.log(data);
        }
    })
} 
</script>
</body>
</html>

而這個的實現原理實質是和以前寫的源碼同樣

結論:

優勢:

1.經過jsonp的傳輸方式咱們能夠繞開瀏覽器同源策略。

2.頁面不用刷新而得到數據

缺陷:

1.遠程數據的本地須要將數據封裝在函數中

2.本地須要定義被封裝的函數

3.JSONP只能發送GET請求

下面有個實例:

將JX衛視的節目單取到

index.html的html代碼

{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script src="{% static 'jquery-3.2.1.js' %}"></script>

</head>
<body>
<h1>維基解密</h1>
<input type="button" onclick="jsonp()" value="發送JSONP請求">
<script>

    function list(arg){
        console.log(arg)
    }

function jsonp(){
    $.ajax({
        url:"http://www.jxntv.cn/data/jmd-jxtv2.html",
        type:'GET',
        dataType:'JSONP',
        jsonp:'callback',
        jsonpCallback:'list'
    })
}

//這裏的     jsonp:'callback',jsonpCallback:'list至關於
 url:"http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list",
</script>
</body>
</html>

結果以下:

相關文章
相關標籤/搜索