JSONP

目錄

同源策略介紹html

驗證同源策略python

解決同源策略jquery

網上實例ajax

同源策略介紹

基於安全的緣由,瀏覽器是存在同源策略機制的,同源策略阻止從一個源加載的文檔或腳本獲取或設置另外一個源加載的文檔的屬性。django

 

驗證同源策略

from django.shortcuts import render,HttpResponse
from django.views import View
import json


class Index(View):
    def get(self,request):
        data = {"a":1,"b":2,"c":"中國"}
        return HttpResponse(json.dumps(data))
python模擬服務器端
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>


</head>
<body>
    <h1>haha</h1>

    <input type="button" id="btn1" value="btn1">

    <script src="jquery.js"></script>
    <script>

        $("#btn1").click(function () {
            console.log("btn1");
            $.ajax({
                type:"GET",
                url:"http://127.0.0.1:8000/jsonp/index/",
                success:function(msg){
                    console.log(msg)
                }
            })
        });
    </script>
</body>

</html>
在本地新建一個html文件,調用遠程資源

 

解決同源策略

服務器端直接添加Access-Control-Allow-Origin字段

from django.shortcuts import render,HttpResponse
from django.views import View
import json


class Index(View):
    def get(self,request):
        data = {"a":1,"b":2,"c":"中國"}
        ret = HttpResponse(json.dumps(data))

        # 在頭部添加Access-Control-Allow-Origin字段爲*,在源頭容許跨域,測試有效
        print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8')}
        ret._headers["Access-Control-Allow-Origin"] = ("Access-Control-Allow-Origin","*")
        print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8'), 'Access-Control-Allow-Origin': ('Access-Control-Allow-Origin', '*')}

        return ret
python views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>


</head>
<body>
    <h1>haha</h1>

    <input type="button" id="btn1" value="btn1">

    <script src="jquery.js"></script>
    <script>

        $("#btn1").click(function () {
            console.log("btn1");
            $.ajax({
                type:"GET",
                url:"http://127.0.0.1:8000/jsonp/index/",
                success:function(msg){
                    console.log(msg)
                }
            })
        });
    </script>
</body>

</html>
test.html

使用script的src字段繞過同源策略

簡單使用script的src字段

from django.shortcuts import render,HttpResponse
from django.views import View
import json


# class Index(View):
#     def get(self,request):
#         data = {"a":1,"b":2,"c":"中國"}
#         ret = HttpResponse(json.dumps(data))
#
#         # 在頭部添加Access-Control-Allow-Origin字段爲*,在源頭容許跨域,測試有效
#         print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8')}
#         ret._headers["Access-Control-Allow-Origin"] = ("Access-Control-Allow-Origin","*")
#         print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8'), 'Access-Control-Allow-Origin': ('Access-Control-Allow-Origin', '*')}
#
#         return ret


class Index(View):
    def get(self,request):
        data = {"a":1,"b":2,"c":"中國"}

        ret = HttpResponse(json.dumps(data))
        return ret
python views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>


</head>
<body>
    <h1>haha</h1>

    <input type="button" id="btn1" value="btn1">
    <input type="button" id="btn2" value="btn2">


    <script src="jquery.js"></script>
    <script>
    

        $("#btn1").click(function () {
            console.log("btn1");
            $.ajax({
                type:"GET",
                url:"http://127.0.0.1:8000/jsonp/index/",
                success:function(msg){
                    console.log(msg)
                }
            })
        });
    </script>
    
        <script>

        function CreateScript(src) {
            var Scrip=document.createElement('script');  // 建立script標籤
            Scrip.src=src;  // 設置script的src屬性
            document.body.appendChild(Scrip);
        }

        $('#btn2').click(function(){
            console.log("btn2");
            CreateScript("http://127.0.0.1:8000/jsonp/index/")
        })
    </script>
</body>

</html>
test.html

緣由分析

  • 添加標籤:<script src="http://127.0.0.1:8000/jsonp/index/"></script>
  • 通過服務端返回數據{"a": 1, "b": 2, "c": "\u4e2d\u56fd"},瀏覽器將其解析爲html語言出現錯誤,非數據,好比返回的是字符串「abc」,但瀏覽器會解析爲abc對象。
  • 瀏覽器不知道怎麼處理這些返回來的html代碼

解決方法

  • 若是返回的數據是"func("abc")",那麼瀏覽器就會找到func函數對字符串「abc」進行處理

自定義方法,使用script的src字段,返回帶有callback方法的數據

from django.shortcuts import render,HttpResponse
from django.views import View
import json


# class Index(View):
#     def get(self,request):
#         data = {"a":1,"b":2,"c":"中國"}
#         ret = HttpResponse(json.dumps(data))
#
#         # 在頭部添加Access-Control-Allow-Origin字段爲*,在源頭容許跨域,測試有效
#         print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8')}
#         ret._headers["Access-Control-Allow-Origin"] = ("Access-Control-Allow-Origin","*")
#         print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8'), 'Access-Control-Allow-Origin': ('Access-Control-Allow-Origin', '*')}
#
#         return ret


# class Index(View):
#     def get(self,request):
#         data = {"a":1,"b":2,"c":"中國"}
#
#         ret = HttpResponse(json.dumps(data))
#         return ret


class Index(View):
    def get(self,request):
        callback= request.GET.get("callback")
        data = {"a":1,"b":2,"c":"中國"}

        data = '{func}({data})'.format(func=callback,data=data)
        # data = '{func}("{data}")'.format(func=callback,data=data)  # 若是是字符串,則須要加雙引號

        ret = HttpResponse(data)
        return ret
python views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>


</head>
<body>
    <h1>haha</h1>

    <input type="button" id="btn1" value="btn1">
    <input type="button" id="btn2" value="btn2">


    <script src="jquery.js"></script>
    <script>
    

        $("#btn1").click(function () {
            console.log("btn1");
            $.ajax({
                type:"GET",
                url:"http://127.0.0.1:8000/jsonp/index/",
                success:function(msg){
                    console.log(msg)
                }
            })
        });
    </script>
    
        <script>

        function CreateScript(src) {
            var Scrip=document.createElement('script');  // 建立script標籤
            Scrip.src=src;  // 設置script的src屬性
            document.body.appendChild(Scrip);
        }
        function myjsonpcallback(data) {
            console.log("==================jsonpcallback==================")
            console.log(data)
        }

        $('#btn2').click(function(){
            console.log("btn2");
            // CreateScript("http://127.0.0.1:8000/jsonp/index/")
            CreateScript("http://127.0.0.1:8000/jsonp/index/?callback=myjsonpcallback")
        })
    </script>
</body>

</html>
test.html

直接使用ajax自帶的jsonp,返回帶有callback方法的數據

from django.shortcuts import render,HttpResponse
from django.views import View
import json


# class Index(View):
#     def get(self,request):
#         data = {"a":1,"b":2,"c":"中國"}
#         ret = HttpResponse(json.dumps(data))
#
#         # 在頭部添加Access-Control-Allow-Origin字段爲*,在源頭容許跨域,測試有效
#         print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8')}
#         ret._headers["Access-Control-Allow-Origin"] = ("Access-Control-Allow-Origin","*")
#         print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8'), 'Access-Control-Allow-Origin': ('Access-Control-Allow-Origin', '*')}
#
#         return ret


# class Index(View):
#     def get(self,request):
#         data = {"a":1,"b":2,"c":"中國"}
#
#         ret = HttpResponse(json.dumps(data))
#         return ret


class Index(View):
    def get(self,request):
        callback= request.GET.get("callback")
        data = {"a":1,"b":2,"c":"中國"}

        data = '{func}({data})'.format(func=callback,data=data)
        # data = '{func}("{data}")'.format(func=callback,data=data)  # 若是是字符串,則須要加雙引號

        ret = HttpResponse(data)
        return ret
python views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>


</head>
<body>
    <h1>haha</h1>

    <input type="button" id="btn1" value="btn1">
    <input type="button" id="btn2" value="btn2">
    <input type="button" id="btn3" value="btn3">


    <script src="jquery.js"></script>
    <script>
    

        $("#btn1").click(function () {
            console.log("btn1");
            $.ajax({
                type:"GET",
                url:"http://127.0.0.1:8000/jsonp/index/",
                success:function(msg){
                    console.log(msg)
                }
            })
        });
    </script>
    
    <script>

        function CreateScript(src) {
            var Scrip=document.createElement('script');  // 建立script標籤
            Scrip.src=src;  // 設置script的src屬性
            document.body.appendChild(Scrip);
        }
        function myjsonpcallback(data) {
            console.log("==================jsonpcallback==================")
            console.log(data)
        }

        $('#btn2').click(function(){
            console.log("btn2");
            // CreateScript("http://127.0.0.1:8000/jsonp/index/")
            CreateScript("http://127.0.0.1:8000/jsonp/index/?callback=myjsonpcallback")
        })
    </script>
    <script>
        function myjsonpcallback(data) {
            console.log("==================jsonpcallback==================")
            console.log(data)
        }
    
        $(document).ready(function(){
                $("#btn3").click(function(){
                    console.log("btn3");
                    $.ajax({
                        type:"GET",
                        url:"http://127.0.0.1:8000/jsonp/index/",
                        dataType:"jsonp",
                        jsonp:"callback",  //此爲URL上的參數,url?callback=myjsonpcallback,可修改,好比jsonp:cb,則變爲url?cb=myjsonpcallback
                        jsonpCallback:"myjsonpcallback",  // 回調函數名稱
                        success:function(data){
                            console.log("==================success==================")
                            console.log(data)
                        }
                    })
                })
            }
        )

    </script>

    
    
</body>

</html>
test.html

完整版

from django.shortcuts import render,HttpResponse
from django.views import View
import json


# class Index(View):
#     def get(self,request):
#         data = {"a":1,"b":2,"c":"中國"}
#         ret = HttpResponse(json.dumps(data))
#
#         # 在頭部添加Access-Control-Allow-Origin字段爲*,在源頭容許跨域,測試有效
#         print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8')}
#         ret._headers["Access-Control-Allow-Origin"] = ("Access-Control-Allow-Origin","*")
#         print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8'), 'Access-Control-Allow-Origin': ('Access-Control-Allow-Origin', '*')}
#
#         return ret


# class Index(View):
#     def get(self,request):
#         data = {"a":1,"b":2,"c":"中國"}
#
#         ret = HttpResponse(json.dumps(data))
#         return ret


# class Index(View):
#     def get(self,request):
#         callback= request.GET.get("callback")
#         data = {"a":1,"b":2,"c":"中國"}
#
#         data = '{func}({data})'.format(func=callback,data=data)
#         # data = '{func}("{data}")'.format(func=callback,data=data)  # 若是是字符串,則須要加雙引號
#
#         ret = HttpResponse(data)
#         return ret


class Index(View):
    def get(self,request):
        callback= request.GET.get("callback")
        # data = "abcd"
        data = {"a":1,"b":2,"c":"中國"}
        # data = [1,2,"中國","a"]

        if isinstance(data,str):
            data = '{func}("{data}")'.format(func=callback,data=data)
        else:
            data = '{func}({data})'.format(func=callback,data=data)

        ret = HttpResponse(data)
        return ret
python views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>


</head>
<body>
    <h1>haha</h1>

    <input type="button" id="btn1" value="btn1">
    <input type="button" id="btn2" value="btn2">
    <input type="button" id="btn3" value="btn3">

    <hr>
    <textarea id="text" style="width: 400px; height: 100px;"></textarea>

    
    
    <script src="jquery.js"></script>
    
    <script>
        function myjsonpcallback(data) {
            console.log("==================jsonpcallback==================")
            console.log(data)
            $("#text").val(data)
        }
    </script>
    
    <script>
        $("#btn1").click(function () {
            console.log("btn1");
            $.ajax({
                type:"GET",
                url:"http://127.0.0.1:8000/jsonp/index/",
                success:function(msg){
                    console.log(msg)
                }
            })
        });
    </script>
    
    <script>
        // 自定義方法,使用script的src字段,返回帶有callback方法的數據
        
        function CreateScript(src) {
            var Scrip=document.createElement('script');  // 建立script標籤
            Scrip.src=src;  // 設置script的src屬性
            document.body.appendChild(Scrip);
        }

        $('#btn2').click(function(){
            console.log("btn2");
            // CreateScript("http://127.0.0.1:8000/jsonp/index/")
            CreateScript("http://127.0.0.1:8000/jsonp/index/?callback=myjsonpcallback")
        })
    </script>
    
    <script>
        // 直接使用ajax自帶的jsonp,返回帶有callback方法的數據
    
        $(document).ready(function(){
                $("#btn3").click(function(){
                    console.log("btn3");
                    $.ajax({
                        type:"GET",
                        url:"http://127.0.0.1:8000/jsonp/index/",
                        dataType:"jsonp",
                        jsonp:"callback",  //此爲URL上的參數,url?callback=myjsonpcallback,可修改,好比jsonp:cb,則變爲url?cb=myjsonpcallback
                        jsonpCallback:"myjsonpcallback",  // 回調函數名稱
                        success:function(data){
                            console.log("==================success==================")
                            console.log(data)
                        }
                    })
                })
            }
        )

    </script>

    
    
</body>

</html>
test.html

網上實例

百度搜索框

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    *{margin: 0px;padding: 0px;}
    #sch{width:200px;margin: 50px auto;}
    #tex{width: 200px;height: 20px;}
    ul{border: 1px solid #eee;width: 202px;display: inline-block;}
    ul li{list-style: none;border: 1px solid #ddd;width:200px;height: 20px;text-align: left;line-height: 20px;}
    ul li:hover{background: orange;}
    </style>
</head>
<body>
    <div id = 'sch'>
        <input type="text" placeholder='請輸入關鍵字' id = 'tex'>
        <ul id="test_ul">
            <!-- <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li> -->
        </ul>
    </div>

    <script src="../../static/jquery.js"></script>



    <script>
        // 定義回調函數
        function testcb(data){
            var result = data["s"]
            $.each(result,function(index,item){
                $("<li>").html(item).appendTo("#test_ul")
            });
        }
    </script>

    <script>
        // jsonp獲取數據
        function getData(keyword){
            var params = {'wd': keyword,
                'p': '3',
                //'cb': 'testcb',
                "req":2,
                "sid":"1426_21116_22074",
                "json":1,
                "csor":1,};
            $.ajax({
                async: false,
                //url: "http://suggestion.baidu.com/su",
                url: "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",
                type: "GET",
                dataType: 'jsonp',
                jsonp: 'cb',
                jsonpCallback:"testcb",
                data: params,
                timeout: 5000,
                success: function (json) {
                    console.log(json)
                },
                error: function (xhr) {
                }
            });

        }
    </script>

    <script>
        /* 使用input,keyup等都行
        $("#tex").input(function(){
            var mykeyword = $("#tex").val()
            if(mykeyword.length > 0){
                getData(mykeyword)
            }
        })
        */
        $("#tex").on("input",function(){
            $("#test_ul").empty()
            var mykeyword = $("#tex").val();
            if (mykeyword.length>0){
                getData(mykeyword)
            }
        })
    </script>


    <script>
        // 網上其餘人的作法
        /*
        var oTex = document.getElementById('tex');
        var oUl = document.getElementsByTagName('ul')[0];
        function baiduSU(data){
            var d = data.s
            if(d.length){
                oUl.style.display = 'block';
                var str = '';
                for(var i =0;i<d.length;i++)
            {
                str += '<li>'+d[i]+'</li>'
            }
            oUl.innerHTML = str;
            }else{
                oUl.style.display = 'none';
            }
        }



        oTex.onkeyup = function()
        {
            if(oTex.value != '')
            {
                var oScript = document.createElement('script');
                oScript.src = 'http://unionsug.baidu.com/su?wd='+oTex.value+'&cb=baiduSU';
                document.body.appendChild(oScript);
            }else{
                oUl.style.display = 'none';
            }
        }
        */
    </script>

</body>
</html>
baidu.html

過程json

圖中的url應該是會變的,後面使用python爬取該url跨域

結果瀏覽器

爬取url

import requests
import re

url = "https://www.baidu.com"
method = "GET"
headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0",
}
params = {}

req = requests.request(method=method,url=url,params=params,headers=headers)

target = re.search("sugHost : (.+?),",req.text)
print(target.group(1)[1:-1])  # https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su
爬取url.py

 

參考or轉發

http://www.cnblogs.com/oppoic/p/baidu_auto_complete.html安全

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息