zoukankan      html  css  js  c++  java
  • 【笔记】跨域重定向中使用Ajax(XHR请求)导致跨域失败

    背景:

    1、前端Web中有两个域名,a.com和b.com,其中a.com是访问主站(页面),b.com是数据提交接口的服务器(XHR请求)

    2、a.com中用XHR调用b.com/cerate【没有指定协议】,保存数据,写法如下:

    $.ajax({
        url: "//b.com/create",
        type: 'POST',
        data: requestParams,
        dataType: 'json',
        xhrFields: {
            withCredentials: true
        },
        crossDomain: true,
        async: false,
        success: function (data) {
            // ...
        },
        error: function (ret) {
            // ...
    });
    

      

    3、线上环境中,a.com和b.com的都在Nginx中配置了302强制跳转https

    4、某个测试环境中,a.com没有跳转https,b.com有

    问题:

    1、线上环境,用户访问的是https://a.com,调用接口为https://b.com/create,跨域没有问题。

    2、但是在测试环境中,测试人员直接打开了http://a.com页面,调用接口就变成为http://b.com/create,这里跨域预检时,b.com的Nginx反馈302跳转,报错。

    {"readyState":0,"status":0,"statusText":"NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://b.com/create."}

    分析:

    1、readtState: 0说明请求没有发出去,被浏览器拦截了,可能情况有:

    • url格式不对
    • 跨域失败
    • 参数错误
    • 用户取消
    • 其它...

    2、这里应该是跨域失败的问题,因为报错是faild to load url

    3、之前没有关注过跨域重定向问题,StackOverFlow之:

    https://stackoverflow.com/questions/18539403/chrome-cancels-cors-xhr-upon-http-302-redirect/38810391#38810391

    4、W3C标准 https://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0

    5、总的来说,就是对于非简单请求(XHR等),当跨域预检(Option请求)时,如果出现非20X等时,会直接失败,抛出readtState: 0

    解决方法:

    1、在Ajax中明确https协议,避免b.com预检时返回302

    $.ajax({
        url: "https://b.com/create",
        type: 'POST',
        data: requestParams,
        dataType: 'json',
        xhrFields: {
            withCredentials: true
        },
        crossDomain: true,
        async: false,
        success: function (data) {
            // ...
        },
        error: function (ret) {
            // ...
    });
    

      

    2、修改测试环境a.com下的服务器,保持和线上环境一致,不让用户走到http://a.com,强制走https://a.com访问页面

    总结:

    之前一直觉得:

    请求中不指定协议,使用//自动适配页面url的协议

    是一个标准规范。现在看来,对于简单请求,比如页面跳转、图片加载等确实是一个好的做法,但是对于后端接口请求这类,可能需要具体场景斟酌。这句话可以改为:

    简单请求中不指定协议,使用//自动适配页面url的协议

  • 相关阅读:
    Linux基础之什么是Linux
    JavaWeb之AJAX
    JavaWeb之XML
    JavaWeb之Servlet组件
    JavaWeb之JSP
    JavaWeb之HTTP概述
    JavaWeb之开发环境搭建
    JavaWeb之JQuery
    JavaWeb之javaScript
    ddd领域驱动
  • 原文地址:https://www.cnblogs.com/smileSmith/p/9277060.html
Copyright © 2011-2022 走看看