后端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 |