码农日记

薄洪涛的个人博客

JsonP跨域请求详解

先来了解一下基本的概念,什么叫做跨域?

举个例子,在localhost:8080上有一个ajax请求,代码如下

<script src="js/jquery-1.7.2.js"></script>
<script>
    $(document).ready(function () {
        $("#btn").click(function () {
            $.ajax({
                url: 'http://localhost:9090/xxx',
                type: 'GET',
                success: function (data) {
                    $(text).val(data);
                }
            });
        });
    });
</script>

上述代码的功能是向localhost:9090/xxx以get方式请求数据,但是请求结果如下

image.png

为什么会出现这样的情况呢?

首先我们来了解一个名词——同域,所谓同域,就是相同端口,相同域名,相同协议,浏览器的同源限制策略会限制两个不同域的的脚本进行交互,所以跨域简单来说就是不同域之间脚本的交互,举个例子,就是client.com上面的js不能调用server.com上面的js,对象或者数据,因为不同域;特别要注意,跨域的安全限制是对浏览器而言的,服务器端也有安全限制,待会再说;

解决上述问题的方式有很多,我给大家介绍一种最简单的方式——jsonp方式,看代码

<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
    $(function () {
        $.ajax({
            url:"localhost:9090/public/index.php/admin/index/data",
            dataType: "jsonp",
            data:{},
            jsonp:"callback",
            type:'get',
            success:function (data) {
                console.log(data);
            }
        });
    });
</script>

可以看到,和最初的代码相比较,多指定了dataType字段和回调函数名字

后端以php为例

 public function data(){
   if($this->request->isGet()){
       $fn = $this->request->get('callback');
       $data_dyj = Db::name('lottery_phoenix_tree')->order('id','desc')->limit(1)->select();
       $data_ssq = Db::name('lottery_phoenix_tree_ssq')->order('id','open_time')->limit(1)->select();
       $this->res['code'] = '200';
       $this->res['data_ssq'] = $data_ssq[0];
       $this->res['data_dyj'] = $data_dyj[0]["content"]; 
       $arr = json_encode($this->res);
       return $fn."($arr)";
   }
 }

解释一下,$fn是ajax传递过来的回调函数的名字,返回的时候,把返回结果json化后,当做回调函数的参数传递进去;

注意事项:

1,type必须为get,即使指定了post,也会自动转换成get,但是服务器端设置了post接收,就接受不到传递的参数;

2,必须制定dataType为jsonp,这个不用多说;

记:如果是jsonp跨域,可以不指定header头

可以看到jsonp指定服务器返回的数据类型为jsonp格式,可以看发起的请求路径,自动带了一个callback=xxx,xxx是jquery随机生成的一个回调函数名称。


如果服务器端设置Access-Control-Allow-Origin,来实现跨域,可以使用普通的ajax直接跨域了

以php为例,参照后端代码如下

header("Access-Control-Allow-Origin: http://a.com"); // 允许a.com发起的跨域请求  
//如果需要设置允许所有域名发起的跨域请求,可以使用通配符 *  
header("Access-Control-Allow-Origin: *"); // 允许任意域名发起的跨域请求  
header('Access-Control-Allow-Headers: X-Requested-With,X_Requested_With');

image.png



发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Powered By Z-BlogPHP 1.7.3

版权所有 | 转载请标明出处