一般情况下 shiro在session过期,权限验证不通过都会跳转到登录页面,但是我的项目中使用了easyui框架,跳转后并没有跳转到登录页面,但是在页面查看网络请求确实跳转到登录页面,但是页面并不加载,经过排查问题如下:
问题1:session失效没有跳转到登录页面
1)排查shiro的配置文件登录设置正确
//如果不设置,默认自动寻找web工程根目录下的“login.jsp”页面
shiroFilterFactoryBean.setLoginUrl("/login");
2)查看浏览器是否重定向到登录页面
已经重定向到登录页面页面,而且还不是一个。
3)经过排查发现加载的login不是在框架的顶部,通过发下在重定向的时候要top.localhost.href才可以重定向,但是咱们去修改shiro是他的重定向加上top呢,通过查看shiro源码 发现所有的拦截验证不通过都要走FormAuthenticationFilter过滤器。
在FormAuthenticationFilter中对方法
onAccessDenied进行重写
源码:
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
//判断是不是登录请求
if (isLoginRequest(request, response)) {
if (isLoginSubmission(request, response)) {
if (log.isTraceEnabled()) {
log.trace("Login submission detected. Attempting to execute login.");
}
return executeLogin(request, response);
} else {
if (log.isTraceEnabled()) {
log.trace("Login page view.");
}
//allow them to see the login page ;)
return true;
}
} else {
//不是登录请求
if (log.isTraceEnabled()) {
log.trace("Attempting to access a path which requires authentication. Forwarding to the " +
"Authentication url [" + getLoginUrl() + "]");
}
saveRequestAndRedirectToLogin(request, response);
return false;
}
}
我们对不是登录请求的方法进行重写
public class ShiroFormAuthenticationFilter extends FormAuthenticationFilter {
public static final String DEFAULT_PATH_SEPARATOR = "/";
private String pathSeparator = DEFAULT_PATH_SEPARATOR;
/* @Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
return false;
}*/
/**
* 重写验证失效后
* @param request
* @param response
* @return
* @throws Exception
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
if (isLoginRequest(request, response)) {
if (isLoginSubmission(request, response)) {
return executeLogin(request, response);
} else {
return true;
}
} else {
String requestURI = getPathWithinApplication(request);
System.out.println(requestURI);
HttpServletRequest httpServletRequest = (HttpServletRequest)request;
System.out.println(httpServletRequest.getContextPath());
String[] pattDirs = StringUtils.tokenizeToStringArray(requestURI, this.pathSeparator);
//是ajax请求重定向
if(isAjax(request)){
//if(pattDirs.length>0&&!"system".equals(pattDirs[0])) {
PrintWriter out = response.getWriter();
out.println("8888");
//}
}else{
//针对前段请求window.location.href
if(requestURI!=null&&requestURI.contains("/doc")){
response.setContentType("textml;charset=gb2312");
PrintWriter out = response.getWriter();
out.println("");
}else {
//针对Form表单提交
this.saveRequestAndRedirectToLogin(request, response);
}
}
return false;
}
}
private static boolean isAjax(ServletRequest request){
String header = ((HttpServletRequest) request).getHeader("X-Requested-With");
if("XMLHttpRequest".equalsIgnoreCase(header)){
return Boolean.TRUE;
}
return Boolean.FALSE;
}
}
我们发现这个重写的类并没有进行加载
需要在shiro的配置文件中进行过滤配置
在shiroConfig.java中配置
//自定义过滤类
ShiroFormAuthenticationFilter shiroFormAuthenticationFilter = new ShiroFormAuthenticationFilter();
Map filterMap = new HashMap<>();
filterChianDefintionMap.put("/**","user,authc");
filterMap.put("user",shiroFormAuthenticationFilter);
shiroFilterFactoryBean.setFilters(filterMap);
这样在shiro加载的时候加载了这个Filter
js修改
针对Form提交重定向后 页面不能加载问题,在登录页做一下改动
$(function(){
if(top==window){
}else{
top.alert("由于你长时间没有操作,导致Session失效!请你重新登录!",top.location.reload())
}
})
针对ajax请求js做的改动
在首页中加
$(function(){
$.ajaxSetup({
complete:function(XMLHttpRequest){
console.log("sessionStorage:"+sessionStorage.getItem("itemvalue"));
if(XMLHttpRequest.responseText==8888&&(sessionStorage.getItem("itemvalue")==null||
(new Date().getTime()-sessionStorage.getItem("itemvalue")>100000))){
top.alert("由于你长时间没有操作,导致Session失效!请你重新登录!",top.location.href= ctx + "/login");
sessionStorage.setItem("itemvalue",new Date().getTime());
};
}
})
})
对ajax请求加默认参数