解决AJAX在用户登录失效后返回登录页面的问题

   后端AJAX API,Session过期,登录失效,直接跳转(redirect)到登录页。(后端Shiro、Spring Security等都支持这个功能)

 

    对于全站AJAX的应用,当然不存在redirect重定向到登录页面的做法(建议直接返回HTTP Code 401),但是对于某些前后端没有分离的应用,当用户session失效时,后端可能会重定向到登录页面。那对于ajax请求,后端重定向后,返回的ajax内容是一个html页面,怎么办呢?

    总体的思路是在ajax工具的拦截器中做一些特殊的判断。

1、jquery ajax的具体解决办法(示例)如下:

//全局配置

$.ajaxSetup({

    dataType: "json",

    contentType: "application/json",

    cache: false,

    complete: function (jqXHR, status) {

      if(jqXHR.status==200) {

        return;

      }

      if(jqXHR.status==401) {

        var loginPage = 'sys/logout';

        // 处理iframe页面

        if (top) {

          top.location = loginPage

        } else if (parent) {

          parent.location = loginPage

        } else {

          window.location = loginPage

        }

      }

      if(jqXHR.status==403) {

        alert('对不起,你没有权限,若有疑问请联系管理员。<br/>(Access is not allowed. HTTP CODE: 403)');

      }

      if(jqXHR.status==500) {

        alert('请求出错啦,请稍后再试试看。<br/>(Server internal error. HTTP CODE: 500)');

      }

      if(jqXHR.getResponseHeader("content-type") == "text/html") {

        document.write(jqXHR.responseText);

        document.close();

      }

  }

});

代码说明,注意到最后一个if,判断如果ajax返回的是一个页面,则直接document.write显示(如果是登录页,就会直接替换到当前的其他页面)。

 

2、axios的判断方法如下(原理一样):

axiosInstance.interceptors.response.use(

  response => {

    console.log(response)

    // session 超时....

    if (response.status === 401

        || response.headers['content-type'] === 'text/html') {

 

      store.dispatch('FedLogOut')

    } else {

      return response

    }

  },

  error => {

    console.log(error)

    // 若path为登录url,则跳转

    if(error.response.path='/login.html') {

      store.dispatch('FedLogOut')

    }

    return Promise.reject(error)

  }

)

    原理同上面一样,只不过在error处,也做了一个判断。因为后端页面重定向时,在axios中,是不会执行response =>{...}的,但是error=>{...}函数会执行。这个方法官方文档没说明,也是我摸索了十几分钟才试出来的。特此记录分享出来。

 

    另外,后端也有进一步优化的空间——那就是精确判断Request请求是否为AJAX类型。如果是AJAX请求则未登录时返回401状态码,如果不是AJAX请求,则重定向到登录页面。

    优化空间在于,怎么尽量准确地判断请求是否为AJAX类型?我写了一个Java方法如下:

/**

 * 判断是否为Ajax类型的请求(支持jquery,其他方式未测试过)

 */

public static boolean isAjaxRequest(HttpServletRequest request) {

    String header = request.getHeader("X-Requested-With");

    if (header != null && "XMLHttpRequest".equals(header)) {

        return true;

    }

    return false;

}

    注意看代码注释,很显然,这个方法不够准确,甚至在某些情况下完全失效。

    那怎么办呢,可以根据Header内容来判断,通常AJAX请求的header里面有一些特点的内容,这有助于精确判断请求是否为AJAX类型。另外,判断header中accept的值,如果是类似下面的格式(以application/json开头),通常都是AJAX请求:

// ajax

application/json, text/javascript, */*; q=0.01

application/json, text/plain, */*

// 非ajax

text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值