JsonP跨域请求详解

薄洪涛6年前JS1285

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

举个例子,在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



标签: 跨域

相关文章

js复制Dom节点内容到系统剪切板

需求:密码生成器,生成后比较长的密码串,点击复制按钮,实现复制到系统剪切板;这里使用到一款js插件:可以实现一键复制 https://github.com/zenorocha/clipboard.js...

融云搭建IM在安卓微信浏览器无法播放声音

融云搭建IM在安卓微信浏览器无法播放声音

之前我们做了一个在线问诊的项目,基于融云和VUE搭建,在聊天的时候,接收到语音消息进行播放的时候,出了点问题,在安卓的微信浏览器上无法播放,在ios上却可以然后我使用了微信开发者工具,打开了页面,发现...

vue如何在移动端调试

vue如何在移动端调试

    最近配合做vue的项目开发,我们前端遇到了一些问题,在调试android和ios样式兼容的时候,需要在手机上调试,但是又需要部署包发到服务器上,然后才能...

node学习及小爬虫的实现

node学习及小爬虫的实现

菜鸟一只,抽空了解了下node,然后总结下学到的重点;首先是安装nodejs,需要安装的版本最好是v6.0以上,不然有些特性不兼容nmp是和nodeJS一起安装的一个管理包工具,类似于python的p...

vue搭建基于融云的聊天室

    最近项目比较忙,在做完了一个在线问诊的项目后,想给大家分享下其中用到的,但是百度上资料又比较少的技术    需求...

vue2.0搭建vue脚手架

vue2.0搭建vue脚手架

最近有个项目,老大评估后想用前后端分离技术来做,借这个机会来熟悉下vue前端框架,这次就搭建一个vue项目,下一个目标就是把vue和yii2.0整合;开搞搭建node环境这步很简单,下载安装包右键安装...

发表评论    

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