• jQuery ajax 302跨域


    一、ajax 302


    ajax用于异步获取服务器数据,但是某天有这么一个使用场景:

    > 基于安全考虑,登录的用户的信息失效时,系统的所有ajax接口都由服务器直接重定向到系统的登录页面,此时登录页面与系统属于同一个域;
    

    于是否,使用ajaxComplete的方法为系统所有ajax统一设置请求完成后的回调,判断其http的status code是否为302,类似于下面代码:

    $(document).ajaxComplete(function(e, xhr, settings){
        var _location;
        console.log(xhr);
        if(xhr.status === 302){
            _location = xhr.getResponseHeader("Location");
            if(_location) {
                location.assign(_location);
            }
        }
    });
    
    //获取数据的接口
    $.ajax({
        url: "/api/fetch.html"
    }).always(function(ret){
         console.log(ret);
    });
    

    可是测试结果显示,ajax的回调在重定向之后死活没有执行,直至获取重定向后的请求才会执行ajax的回调,也就是说重定向后的内容作为ajax的接口内容来响应。此时可以看到浏览器控制台输出的ret内容不是json字符串,实际上为系统重定向到登录页面的html字符串。


    为什么会出现这样的结果呢?

    在stackoverflow上可以找到讨论的答案

    > You can't handle redirects with XHR callbacks because the browser takes care of them automatically. You will only get back what at the redirected location.
    

    也就是说,重定向是由浏览器自动透明的完成的。所以服务器将302响应发给浏览器时,浏览器并不是直接处理ajax的回调,而是先执行302重定向。这就是上面例子中为什么获取不到xhr.status为302的值。

    一个ajax请求的重定向大致流程是这样的:

    ajax --> browser --> server --> 302 --> browser(redirect) --> server --> browser --> ajax callback
    

    注意,上面ajax获取不到xhr的status是有一个前提:即,服务器为response设置了*Location* header

    因为,浏览器在发现Location的header时就会自动跳转到Location所指定的URL地址,类似于用js来进行重定向;不过这个重定向只有浏览器知道。
    

    所以,在ajax接口返回302时,而没有设置Location的header时,这个xhr的status值还是能获取到的,下图是在浏览器控制台测试的结果:

    可以看到服务器给response的header添加了Location1的header,浏览器并不认识,所以不会重定向,此时或可以获取xhr的status为302

    二、ajax 302跨域


    随着公司业务的发展新的情况出现了,公司要将登录认证统一到某台公共的服务器上,这时,失效的用户在ajax获取数据时状态失效而被重定向到登录页面;由于当前系统与登录页面不同域,而XHR不允许跨域访问数据,所以ajax的302也存在跨域问题。(不像页面之间重定向不存在这个问题,你可以访问当前系统的某个页面,服务可以重定向到www.baidu.com而不会有跨域问题)。

    这时,由于存在跨域,浏览器不会进行重定向;但是能否通过上面的代码来用JavaScript进行重定向呢?

    抱歉,同样不可以;这时通过ajaxComplete方法获取到的xhr的status值,发现其值为0,Location的header为null;所以这种办法行不通。更可取的方法可以是这样:

    首先不要在服务器端进行重定向;然后通过接口的形式或者在response添加一个自定义header来区分重定向信息;最后由JavaScript来进行重定向
    

    三、xhr status为0的问题


    翻看W3C文档,发现xhr的status值由以下三个步骤来决定:

    The status attribute must return the result of running these steps:
    
      1.  If the state is UNSENT or OPENED, return 0.
    
      2.  If the error flag is set, return 0.
    
      3.  Return the HTTP status code.
    

    第二条的error flag:The error flag indicates some type of network error or fetch termination. It is initially unset.

    通过上面得知:

    在调用xhr的open方法还没有调用send方法,或者xhr出错了(如跨域就会发生网络错误)都会导致xhr state为0的情况
    

    最常见的两种xhr status为0的情况:

    • ajax发送后还没有得到响应前立即刷新浏览器,这时ajax就会被浏览器给丢弃了,会返回status code为0;这主要发生在form表单的提交用ajax来提交,而没有阻止表单提交的默认行为,导致页面刷新,这时ajax发出了,但页面刷新; 其实ajax能得到xhr的status只不过值为0;

    • xhr跨域,包括异步请求跨域和302跨域的情况,这时会出现xhr status为0的情况

    参考文献

  • 相关阅读:
    VHDL硬件描述语言(三)——基本数据对象和数据类型
    VHDL硬件描述语言(二)——子程序
    VHDL硬件描述语言(一)——基本结构
    C#类
    C#基本语法
    C#的简单数据类型
    C#与.NET
    ARP
    IPv6
    以太网
  • 原文地址:https://www.cnblogs.com/wonyun/p/5696838.html
Copyright © 2020-2023  润新知