为什么现在JSONP也不能进行跨域请求了?

古道西风瘦马
  • 352
  • 浏览器:chrome 96。
  • 问题描述:我在test.html中使用了jsonp请求,发现浏览器报了跨域的错误。了解jsonp的都知道jsonp就是动态创建一个script标签引用服务器返回的js代码,这段代码里面写了一个函数调用。那么就是说我引用外域的JS文件会导致跨域问题,但是很奇怪的是,我的代码里也引用的cdn加速的jquery文件啊,这个Jquery文件和我的html文件也没在一个服务器啊,为什么jquery这个script链接不报跨域错误呢?那么是不是说可以通过配置服务器来解决这个问题呢?
    我尝试了取消使用jsonp求请求去获取这个文件,改成直接在html文件写入script标签来引用这个文件,果然还是出现了跨域的问题。
    请问如果处理这个问题?可以直接更改我要请求的服务器的配置来解决么?尽量不使用nginx反向代理来解决。 因为我希望这个jsonp请求能像引用jquery的cdn链接一样简单。

有同学要我贴代码以及让我在不同浏览器尝试,其实我是有尝试的,我再补充下相关说明

  • 补充说明:我在chrome96中是有跨域问题的,但是IE11中是没有问题的。
  • 代码:

    <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; " charset="UTF-8">
      <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script>
      <script type="text/javascript">
          function doSubmit() {
              var username = document.getElementById("username").value.trim();
              var password = document.getElementById("password").value.trim();
              if (username === "") {
                  window.alert("请输入用户名");
                  return false;
              }
              if (password === "") {
                  window.alert("请输入密码");
                  return false;
              }
              var url = "http://000.000.000.000:8081/webroot/decision/login/cross/domain" + "?fine_username=" +encodeURIComponent(username) + "&fine_password=" + encodeURIComponent(password) + "&validity=" + -1;
              alert(url);
              jQuery.ajax({
                  url: url,//单点登录的管理平台报表服务器
                  timeout: 5000,//超时时间(单位:毫秒)
                  dataType:"jsonp",//跨域采用jsonp方式
                  jsonp:"callback",
                  success: function (res) {
                      console.log(res);
                      if (res.errorCode) {
                          window.alert(res.errorMsg);
                      }else {
                          // 保存token并跳转到对应链接
                          window.location.href = "http://localhost:8080/webroot/decision";
                      }
                  },
                  error: function () {
                      alert("超时或服务器其他错误");// 登录失败(超时或服务器其他错误)
                  }
              });
          }
          function callback (res) {
            console.log('script',res)
          }
      </script>
    </head>
    <body>
    <p>请登录</p>
    <form id="login" name="login" method="POST" action="">
      <p>用户名:<input id="username" type="text" name="username"/></p>
      <p>密 码:<input id="password" type="password" name="password"/></p>
      <input type="button" value="登录" onClick="doSubmit()"/>
    </form>
    <script src="http://000.000.000.000:8081/webroot/decision/login/cross/domain?fine_username=admin&fine_password=Aa123456&validity=-1"></script>
    </body>
    </html>
  • chrome报错截图
    image.png
回复
阅读 3.3k
10 个回答

跨域有三个项 协议域名端口

你不会是 https 请求 http 了吧?

其他原因还有可能是 CSP 之类的。也有可能是 cookie 没带过去,导致响应不对之类的

MIME type是对text/plain,受到了chrome的CORB保护,跨域请求完成,但是没有读取里面的内容。把它改成text/javascript再试试

根据Chrome的CORB特性,以下情况会被阻挡:

  • HTML, XML, JSON内容
  • X-Content-Type-Options: nosniff
  • 没有显式声明CORS

所以虽然返回的内容是javascript,但MIME类型是text/plain, text/html, text/xml, text/json还是会被阻挡。甚至不会进入Chrome进程的内存空间。

所以需要联系对方修改Response的MIME类型。

看问题描述,最大可能是test的http头的同源策略,并且添加了允许jquery域名,具体的错误,在浏览器控制台上能看到更详细的信息。

原则上jsonp这个很hack的方式,也需要后端配合支持。
比如这个接口想要以jsonp的方式请求,起码响应得是JavaScript脚本,不然你的callback怎么执行

首先,script标签没有跨域限制

我尝试了取消使用jsonp求请求去获取这个文件,改成直接在html文件写入script标签来引用这个文件,果然还是出现了跨域的问题。

这句话如果是真的,说明服务器设置了一些防盗链措施,直接引用是走不通的。

我在chrome96中是有跨域问题的,但是IE11中是没有问题的。

这句话又说明,服务端并没有防盗链,一般引用是正常的。

jQuery.ajax({
              url: url,//单点登录的管理平台报表服务器
              timeout: 5000,//超时时间(单位:毫秒)
              dataType:"jsonp",//跨域采用jsonp方式
              jsonp:"callback",
              success: function (res) {
              ...
              function callback (res) {
              ...

虽然不太懂,不过jsonp写法应该是错的,jQuery使用jsonp只需要dataType:"jsonp",需要指定回调函数的时候使用jsonpCallback: "函数名",需要修改服务端接受回调函数名的时候使用jsonp:"callback"


结论

先把jsonp:"callback"去掉,jQuery默认就是这个参数,想指定回调函数就使用jsonpCallback: "函数名"

问题描述前后有些矛盾,总之jsonp是需要服务端配合的。

想解决问题,先看看服务端正常请求的时候返回的回调函数是什么,再去改ajax代码。

看报错是至少有一个MIME type是text/plain的问题
ie11没问题是因为ie11古老,没有支持最新的安全策略,你换edge肯定也会有问题
想要解决必须要后端层面去解决

你的代码中同时有https去请求的jquery,也有http去请求你的jsonp?
你的页面访问到底是基于https的还是http的?
现代浏览器对于这个要求是比较高的,要么全https,要么全http,混合就是不行的。

是 CORB 的原因

详情见 https://segmentfault.com/a/11...

简单地说就是你的 script 的标签的 url 返回的 header 的 MIME type 是 text/plain 不匹配 text/javascript

浏览器会禁止执行此代码

这个是目前chrome内核浏览器安全策略问题导致的,你请求jsonp网页的域名非https或localhost就会提示跨域,按下面操作可零时解决。
浏览器地址栏输入:
chrome://flags/#block-insecure-private-network-requests
选择禁用
disabled
重启浏览器就可以使用了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏