Ajax接口跨域问题JSONP解决方式

前言:

    其实跨域的出现主要是因为浏览器的同源策略导致的,那什么又是浏览器的同源策略呢???。

同源策略

        概念:协议,域名,端口  3者相同就是同源,

                   反之3者中有一个不同, 则是不同源 【不同源接口请求,就会出现跨域

        作用:浏览器的同源策略主要是为了保证用户信息的安全而出现。

       那什么情况下属于同源,什么情况下是不同源呢,看下图

在这里注意一下啊,这里是为了突出端口的区别才写上端口。

在默认情况下 http 可以省略端口 80 https 省略 443

这别到时候闹笑话了,你和我说 http://www.example.com:80 和 http://www.example.com 不是同源,他俩是一个东西。

http://www.example.com:80 === http://www.example.com

https://www.example.com:443 === https://www.example.com

解决方案---JSONP

JSONP 是 JSON with Padding 的简称 ,是一种较为常用的解决跨域访问的方式。

jsonp 解决跨域问题的本质:就是利用 script 标签的 src 属性来进行,由于script标签的src属性不受跨域的限制,

所以我们可以将我们要请求的 服务器地址及相关参数 作为 src的值 来进行传输,然后再由后台进行配合就可以实现跨域。

我们先来看一段示例代码:

ajax({//此ajax方法是封装了XMLHttpRequest对象实现,具体代码与本文无关就不贴了
  method : 'get',
  url : 'http://127.0.0.1:8787',
  data : {
  'name' : '小明',//此ajax方法会自动将数据以get方式提交
  'age' : 22
  },
  success : function (message) {
    alert(message);
  },
  async : true
})

上面的代码很简单,浏览器端发起了一个异步ajax请求,让我们来看看服务端代码:

app.get('*', function(req, res) {//这里只截取了关键代码
  res.send("测试数据");
});
 

不出所料,浏览器甩了我一脸...


不要担心,我们重振旗鼓再战!JSONP 炸裂炫酷出场~

步骤1: 

     1: 在客户端全局作用域下定义函数showJsonp,作为后端返回给我们函数的调用,

        如果这个函数不是全局的话,我们在调用的时候会报错,而且这个一定要在前面。

     2: 将 不同源的服务器端请求 地址写在 script 标签的 src 属性中,

---------------js里面
// 在全局作用域下定义回调函数showJsonp
function showJsonp(obj){
  console.log(obj.message);
}
var url = 'http://127.0.0.1:8787/?msg=hello&cb=showJsonp' // cb参数名为showJsonp
var script = document.createElement('script');

script.setAttribute('src',url);
script.setAttribute('type','text/javascript');
document.getElementsByTagName('head')[0].appendChild(script);

// script.src = url
// document.body.appendChild(script);
// script.onload = function () {
    // document.body.removeChild(script)
// }


------------或者直接在html里面写
<body>
    <script>
        function fn(data){
            console.log(data.message);
            console.log("ok函数调用了")
        }
    </script>
    <script src="http://127.0.0.1:8787/test?msg=hello&cb=showJsonp"></script>

</body>
<script src="https://cdn.bootcss.com/jquery/3.5.0/jquery.min.js"></script><script>
  $.ajax({
    url: "http://localhost:8080/api/jsonp",
    dataType: "jsonp",
    type: "get",
    data: {
      msg: "hello"
    },
    jsonp: "cb",
    success: function(data) {
      console.log(data);
    }
  });
</script>


再来看看后台代码~ 

   3: 服务器端响应的必须是一个函数的调用,真正要发送给客户端的数据要作为函数调用的参数

app.get('*', function(req, res) {
  // let callback = req.query.cb;
  let { cb, msg } = req.query;

  let content = cb + "({'message':'测试数据2', 'say': JSON.stringify(msg)})";
  res.send(content);
});

结果

大!获!全!胜!


我们来分析一波战术策略了~

在平常写代码的时候,可能很多人没有注意,浏览器对于scriptiframe等标签的 src 等属性,是 没有 同源策略 限制 的。

jsonp 就很好的利用了这一点~,在我们发起请求时,url 后跟了一个名为 func 的参数,而这个 参数 就是之后需要用到的 回调函数名称
我们通过动态插入 script 标签的方式,利用 script 标签的 src 属性发起请求,浏览器就不会以同源策略来找事了.......完美!!

而后台根据请求构造出的数据长啥样呢?

showJsonp({'message':'测试数据2'})

告诉我!这段代码插入你的 script 标签内后,会发生啥?!
当然是执行早就定义好的 showJsonp 函数 啊~
bingo,完美解决跨域问题~~


最后

jsonp 的方式兼容性非常好,即便是那些老古董浏览器,也可以用 jsonp 的方式解决跨域问题,

但是它也有所限制,它只能使用 get 方式发起请求,

并且对于不同域名之间页面的 js 互相调用无能为力

注意的是:利用该方法实现是需要 前端 和 后端 配合的。 


如果前端要连接传统后台服务器-----【接口跨域】

分部署时的跨域方案和调试时的跨域方案,具体见下:

一:部署时的跨域方案

        方案1: 最省事的    将前端代码 和 后端接口部署在同域的web服务器上

        方案2: 由后台服务器配置策略,设为允许跨域访问

二:调试时的跨域解决方案

1: 使用HBuilderX(专为vue打造的编译器)内置浏览器

2: 使用 webapck-dev-server  配置代理

module.exports ={
   devServer: {
       // proxy属性:用来添加代理服务配置的,每一个属性,就是一个代理规则的配置
       "proxy": {
           "/prefix/api/user/list": {
                "target": "https://api-remote.xxxx.com",
                "pathRewrite": {
                     "^/prefix": ""
                 }
            }
       }
   }

}

-------修改前端接口请求方式,改为不带域名。(因为现在是同域请求了)
<button id="getlist">获取列表</button>
<button id="login">登录</button>
<script src="https://cdn.bootcss.com/axios/0.19.2/axios.min.js"></script>
<script>  
 axios.defaults.withCredentials = true;  
 getlist.onclick = () => {
    axios.get("/api/corslist").then(res => {
      console.log(res.data);
    });
  };
  login.onclick = () => {
    axios.post("/api/login");
  };
</script>

      前端开发如何独立解决跨域问题 ----->【charles(类似fiddler)正向代理 和 nginx反向代理】

3: 给浏览器安装插件,禁止浏览器报跨域

   前言:

         当我们本地服务器预览页面时,是直接通过本地IP地址去访问开发中的页面,同时这个页面会调一些现有的接口时,就面临着跨域的问题。

比如:本地预览的地址是:http://localhost:8080/,访问的接口地址是http://dcloud.io/api 

 如果仅仅是为了 本地预览,可以使用 Chrome浏览器插件 来协助调试,本插件只能解决简单请求的跨域调试(点击搜索什么是简单请求),对于非简单请求的OPTION预检(点击搜索什么是预检请求)以及线上服务器也有跨域需求的用户,可以服务端配合解决

Chrome插件名称:Allow-Control-Allow-Origin: *

安装方式:

   

使用方式

  1. 打开待调试的页面
  2. 在扩展栏目找到安装的插件,点击打开插件配置
  3. 输入想要进行跨域调试的接口的地址,点击添加即可

注意事项

  • 此插件适合本地调试使用线上部署如果和接口不同域还需要服务端配合
  • 如果实际响应的内容与浏览器预期的内容有差异还可能被CORB策略所阻止。

firefox跨域插件

firefox跨域插件(注意firefox的css兼容问题)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值