解决AJAX在用户登录失效后返回登录页面的问题
对于全站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