拦截ajax请求跳转登录页面
- 场景
- 原因
- 解决方法
- 后台代码
- 前台
场景
项目中使用springMVC的HandlerInterceptorAdapter拦截器拦截请求,如果session失效时,就自动跳转登录页面,但是如果是ajax请求时,就出现不能自动跳转登录页面的情况,也就是ajax请求的转发重定向都失效。
原因
参考:https://blog.csdn/mozha_666/article/details/86519642
简单概括为:
- ajax是局部刷新,不重写加载页面的,请求的最终结果都会返回到ajax封装的方法中。
- ajax默认是不支持重定向的
解决方法
因最终的跳转不能在后台去执行,所以需要配合后端何前台一起协作来完成,后台打标机,前台根据标机跳转。
后台代码
- 判断是否是ajax请求
/**
* 判断是否为ajax请求
*
* @param request
* @param response
* @return
*/
private boolean isAjaxRequest(HttpServletRequest request, HttpServletResponse response) {
try {
//判断是否为ajax请求。
if (request.getHeader("x-requested-with") != null && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
- 如果是ajax请求则打一个标记
/**
* ajax请求标记
*
* @param request
* @param response
* @param loginUrl
*/
private void ajaxHttpToLogin(HttpServletRequest request, HttpServletResponse response, String loginUrl) {
//如果是ajax请求响应头会有x-requested-with,自定义707状态码为ajax登录过期
try {
response.setHeader("SESSIONSTATUS", "TIMEOUT");
response.setHeader("CONTEXTPATH", request.getContextPath() +loginUrl);
response.setStatus(HttpServletResponse.SC_FORBIDDEN);//403 禁止
}catch (Exception e){
e.printStackTrace();
}
}
- 拦截器调用,如图:
前台
ajax属性介绍:http://www.w3school/jquery/ajax_ajax.asp
前台的方法有两种,但是都是通过ajax的后置处理函数来完成的。
- 通过ajax的后置处理函数complete实现:
$.ajaxSetup({
complete : function(XMLHttpRequest, textStatus) {
//拦截器实现超时跳转到登录页面
// 通过xhr取得响应头
var SESSIONSTATUS = xhr.getResponseHeader("SESSIONSTATUS");
//如果响应头中包含 TIMEOUT 则说明是登录过期
if (SESSIONSTATUS == "TIMEOUT"){
var win = window;
while (win != win.top){
win = win.top;
}
//重新跳转到 login.html
win.location.href = xhr.getResponseHeader("CONTEXTPATH");
}
}
});
问题: 实现了complete后,可能某些组件里面实现了complete的会有影响。
- 重写ajax函数
/**
* 重写ajax方法,使ajax登录失效时能正常跳转登录页
*/
function rewriteAjax() {
//首先备份下jquery的ajax方法
var _ajax=$.ajax;
//重写jquery的ajax方法
$.ajax=function(opt){
//备份opt中error和success、complete方法
var fn = {
error:function(XMLHttpRequest, textStatus, errorThrown){},
success:function(data, textStatus){},
complete:function(data, textStatus){}
}
if(opt.error){
fn.error=opt.error;
}
if(opt.success){
fn.success=opt.success;
}
if(opt.complete){
fn.complete=opt.complete;
}
//扩展增强处理
var _opt = $.extend(opt,{
error:function(XMLHttpRequest, textStatus, errorThrown){
var SESSIONSTATUS = XMLHttpRequest.getResponseHeader("SESSIONSTATUS");
//如果响应头中包含 TIMEOUT 则说明是登录过期
if (SESSIONSTATUS != "TIMEOUT"){
//错误方法增强处理
fn.error(XMLHttpRequest, textStatus, errorThrown);
}
//登录的错误处理不用管,直接放行
},
success:function(data, textStatus){
//成功回调方法增强处理
fn.success(data, textStatus);
},
beforeSend:function(xhr){
},
complete: function (xhr,status) {
//拦截器实现超时跳转到登录页面
// 通过xhr取得响应头
var SESSIONSTATUS = xhr.getResponseHeader("SESSIONSTATUS");
//如果响应头中包含 TIMEOUT 则说明是登录过期
if (SESSIONSTATUS == "TIMEOUT"){
var win = window;
while (win != win.top){
win = win.top;
}
//重新跳转到 login.html
win.location.href = xhr.getResponseHeader("CONTEXTPATH");
}
//调用备份的后置处理
fn.complete(xhr, status);
}
});
return _ajax(_opt);
};
}
目前我前台是采用这种形式处理的ajax登录拦截跳转的,对第三方插件的complete目前没有什么影响,不过重写的时候需要慎重
有问题欢迎评论区讨论
更多推荐
拦截ajax请求跳转登录页面
发布评论