一般情況下 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("<script language='javascript' type='text/javascript'>");
out.println("alert('由於你長時間沒有操作,導致Session失效!請你重新登錄!');top.location.href='"+httpServletRequest.getContextPath()+"/login'");
out.println("</script>");
}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<String,Filter> 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請求加默認參數