zoukankan      html  css  js  c++  java
  • ajax跨域原理以及jsonp使用

    jsonp介绍:

    JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。

    由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的<script> 元素是一个例外。

    利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。

    用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。

    默认是由与浏览器的原因使得ajax不能跨域访问:

    本站域名:http://www.py_test1.com:8080/index,

    跨站域名:http://www.py_test2.com:8081/index

    <body>
        <div>
            <input type="button" onclick="ajax_test();" value="跨域"/>
            <p>响应:</p>
            <div class="content">
    
            </div>
        </div>
    </body>
    </html>
    <script>
        function ajax_test(){
            $.ajax({
                url:'http://www.py_test2.com:8081/index',
                dataType:'text',
                type:'post',
                data:{'k1':'v1'},
                success:function(data){
                    $(".content").text(data);
                }
            })
        }
    </script>

    XMLHttpRequest cannot load http://www.py_test2.com:8081/index. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.py_test1.com:8080' is therefore not allowed access.

    实际上信息已经发送到跨站域名网站中,若是信息正确,可以被处理,只是在消息回复到本站时,被浏览器进行了处理报错(同源策略)

    浏览器对于ajax阻止跨域,对于script块,img块,iframe块等,其中具有src属性是允许跨域(相当于发送get请求获得资源),在许多网站中资源引入都使用跨域来完成

    所以可以通过这些src属性进行跨域访问

    办法一:JSONP方法

    <input type="button" onclick="jsonP_test();" value="jsonP跨域"/>
        function jsonP_test(){
            var ele=document.createElement('script');
            ele.setAttribute('src','http://www.py_test2.com:8081/index');
            //添加以后就进行跨域操作
            document.head.appendChild(ele);
            //然后就不需要存在这个标签了
            document.head.removeChild(ele);
        }

    但是这里面获取的资源只是简单的在script中进行了添加

    <script>
        // t2.get    通过get方法跨域到http://www.py_test2.com:8081/index中请求到的某些数据,无法使用
    </script>

    但是如果服务端,即跨域端发送某些函数

        <script>
            // alert(123)    会在页面直接调用弹出窗口
        </script>

    于是可以尝试客户端与服务端进行协商:

    客户端定义好函数,服务端在传递的数据中调用该函数,并且在函数接口中传递参数

    客户端定义函数:

        function func(dt){
            console.log(dt);
        }

    服务端调用并传参:

    self.write('func([11,22,33]);')

    即可在客户端对传递的数据进行处理。

    方法二:对ajax进行修改

        function jsonPajax2(){
            $.ajax({
                url:'http://www.py_test2.com:8081/index',
                dataType:'jsonp',
                jsonpCallback:'func',//发送成功后会自动执行这个函数,不写也会执行,只不过有时候会用到jsonp,需要和jsonpcallback联合使用
                //jsonp:'callback',//会把jsonpCallBack中的数据传送到服务端,服务端就可以对接收的数据进行动态处理,不需要知道客户端的函数名,直接对接收的数据和需要传递的数据进行拼接就可以
            });
        }

    这里需要客户端和服务端进行函数名称保持一致,二服务端似乎对于这个函数名并不是非常感冒,要是传入其他函数名那么久不可用了,复用性太差。所以考虑通过传参将前端的函数名传入服务端,进行灵活调用,来组成字符串

    就有了

       function jsonPaJax(){
            //是jquery对上述jsonp方法的实现和扩展
            $.ajax({
                url:'http://www.py_test2.com:8081/index',
                dataType:'jsonp',
                jsonp:'callback',//会把jsonpCallBack中的数据传送到服务端,服务端就可以对接收的数据进行动态处理,不需要知道客户端的函数名,直接对接收的数据和需要传递的数据进行拼接就可以
                jsonpCallback:'funcx',//发送成功后会自动执行这个函数,不写也会执行,只不过有时候会用到jsonp,需要和jsonpcallback联合使用
            });
        }

    客户端随便定义一个函数,服务端在使用的时候只需要知道这个函数名是在参数callback中,进行调用组合,返回即可

        def get(self):
            #print(self.request.arguments)获取全部参数
            callback=self.get_argument('callback',None)
            self.write('%s([11,22,33]);'%func)

    注意若是客户端jsonpCallback大小写写错,在服务端的callback中会出现'callback': [b'jQuery20004196553791305502_1520586446327']这种情况。

    总结:实际上方法二就是在传入参数中进行了修改,我们也可以写成

    function jsonPaJax(){
            //是jquery对上述jsonp方法的实现和扩展
            $.ajax({
                url:'http://www.py_test2.com:8081/index?callback=func',
                dataType:'jsonp',
                //jsonp:'callback',//会把jsonpCallBack中的数据传送到服务端,服务端就可以对接收的数据进行动态处理,不需要知道客户端的函数名,直接对接收的数据和需要传递的数据进行拼接就可以
                jsonpCallback:'func',//发送成功后会自动执行这个函数,不写也会执行,只不过有时候会用到jsonp,需要和jsonpcallback联合使用
            });
        }

    或者改变方法一:

        function jsonP_test(){
            var ele=document.createElement('script');
            ele.setAttribute('src','http://www.py_test2.com:8081/index?callback=func');
            //添加以后就进行跨域操作
            document.head.appendChild(ele);
            //然后就不需要存在这个标签了
            document.head.removeChild(ele);
        }
  • 相关阅读:
    POJ 1611 : The Suspects (普通并查集)
    深入解析 Dubbo 3.0 服务端暴露全流程
    智能搜索推荐一体化营收增长解决方案
    云上应用系统数据存储架构演进
    EMR on ACK 全新发布,助力企业高效构建大数据平台
    介绍一下闭包和闭包常用场景?
    BFC
    高斯消元学习笔记
    云虚拟主机如何设置域名解析
    Centos7.3安装openJDK
  • 原文地址:https://www.cnblogs.com/ssyfj/p/8534169.html
Copyright © 2011-2022 走看看