[聚合文章] jsonp

JSONP 2017-02-05 15 阅读

1.JSONP原理剖析以及实现

1.1 同源策略限制

用django分别建立两个项目,jsonp01和jsonp02,然后再在这两个项目里分别建立一个app,比如名字叫jsonp1、jsonp2;jsonp01的端口号是8005,jsonp02的端口号是8006。

jsonp1的代码如下,

setting做常规配置;

urls.py,

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^testjsonp/', views.testjsonp),
    url(r'^index/', views.index),
]

views.py,

def testjsonp(request):
    return HttpResponse('OK')


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

index.html,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <input type="button" onclick="ajaxjsonp1();" value="jsonp1" />

    <script src="/static/js/jquery-1.12.4.js"></script>
    <script>
        function ajaxjsonp1() {
            $.ajax({
                url : '/testjsonp/',
                type : 'POST',
                data: {'k1':'v1'},
                success : function (data) {
                    alert(data);
                }

            });
        }

    </script>
</body>
</html>

jsonp2的代码如下,

settings.py做常规配置;

urls.py,

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^testjsonp2/', views.testjsonp2),
]

views.py,

def testjsonp2(request):
    return HttpResponse('jsonp2ok')

如上面的代码,因为jsonp1请求的是自己的项目域名(url : '/testjsonp/'),所以会如期收到返回的数据并alert(ok);

当把url : '/testjsonp/'改成url : 'http://10.103.9.83:8006/testjsonp2/',即用ajax实现跨域请求(好比在www.taobao.com上通过ajax访问www.jd.com的数据),则会报错如下图,

这是因为自身浏览器的同源策略限制,比如在www.taobao.com上通过ajax访问www.jd.com的数据,该请求能从自己的浏览器发送到jd.com服务端,服务端也能处理并返回数据,但是当自己的浏览器发现收到的数据是非本机域名发来的,就会阻拦该数据,过程如下图,

,通过ajax,如果在当前域名去访问其他域名时,浏览器会出现同源策略限制,从而阻止请求的返回,所以无法用ajax实现跨域请求。

1.2 解决同源策略

img、script、iframe、link这些标签是不受同源策略限制的;src属性一般不鸟同源策略。利用这个特点,就可以实现jsonp的跨域请求。

改进jsonp1的index.html的代码,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <input type="button" onclick="ajaxjsonp1();" value="jsonp1" />
    <input type="button" onclick="ajaxjsonp2();" value="jsonp2" />

    <script src="/static/js/jquery-1.12.4.js"></script>
    <script>
        function ajaxjsonp1() {
            $.ajax({
                url : 'http://10.103.9.83:8005 /testjsonp/',
                type : 'POST',
                data: {'k1':'v1'},
                success : function (data) {
                    alert(data);
                }

            });
        }


        function ajaxjsonp2() {
#创建一个script标签,src值设置为要请求的域名,将这个标签加到head标签下,请求完之后remove掉这个标签。
            var tag = document.createElement("script");
            tag.src = "http://10.103.9.83:8006/testjsonp2/";
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }

    </script>
</body>
</html>

然后点击index.html的“jsonp2”按钮,就会收到如下报错:

,这说明本地浏览器已经收到服务端返回的数据(jsonp2ok)了,但是这个返回的数据是交给javascripts处理的,因为script里没有“jsonp2ok”这个方法,所以会报错“jsonp2ok没有定义”,所以需要在服务端和客户端再做一些修改,代码见下,

jsonp2的views.py,

import json
def testjsonp2(request):
    ll = ['jack','luce','goi']

#直接返回一个jsonpfunc(ll),然后客户端的script标签里需要定义一个jsonpfunc方法,然后就能处理数据了。
    temp = 'jsonpfunc(%s)' % (json.dumps(ll))
    return HttpResponse(temp)

jsonp1的index.html,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <input type="button" onclick="ajaxjsonp1();" value="jsonp1" />
    <input type="button" onclick="ajaxjsonp2();" value="jsonp2" />

    <script src="/static/js/jquery-1.12.4.js"></script>
    <script>
        function ajaxjsonp1() {
            $.ajax({
                url : 'http://10.103.9.83:8005 /testjsonp/',
                type : 'POST',
                data: {'k1':'v1'},
                success : function (data) {
                    alert(data);
                }

            });
        }


        function ajaxjsonp2() {
            var tag = document.createElement("script");
            tag.src = "http://10.103.9.83:8006/testjsonp2/";
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }
#收到服务端返回的数据,然后执行下面的jsonpfunc方法。
        function jsonpfunc(data) {
            console.log(data);
        }

    </script>
</body>
</html>

现在再点击jsonp1的index.html的"jsonp2"按钮,返回数据见下:

,客户端收到这些数据后,就可以处理了。

1.3 利用jquery实现伪ajax的跨域请求

上面讲的是jsonp的原理,原理就是利用那些不受同源策略限制的标签来发送请求,下面要说的是利用jquery实现伪ajax的跨域请求。

function weiajax(){
            $.ajax({
                url : 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403',
                type : 'GET',
                dataType : 'jsonp',
                jsonp : 'callback',
                jsonpCallback : 'list'
            });
        }

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

#这样就能获取到江西卫视的节目单了。
#注意,上面的function list(arg){}和 jsonpCallback : 'list',之所以叫list,是因为江西卫视的服务器返回的数据中包含的javascript方法名叫list。

如果用是请求本地域名,就直接用ajax即可;如果是请求跨域数据,则依然用ajax,但是需要dataType : 'jsonp'、jsonp : 'callback'、jsonpCallback : 'funcdemo',然后再定义一个function funcdemo(arg){}方法。

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。