Apache Shiro会话超时,登录页面跳转到父窗体的解决方法

时间:2022-09-17 07:57:00

问题1:

在使用Apache Shiro框架做权限验证时,因为我的页面是使用iframe做了一个上左右的分层,上面上log,左侧是菜单,具体的内容则显示在右侧。

当我点击某菜单,此时如果会话超时了,则登录页面只会显示到右侧区域,看起来不是很友好,所以需要登录页面显示到整个浏览器。


解决方法:

在登录页面做一个跳转,当登录页面不是在顶层显示,则跳转:

window.onload = function () {
if (window.parent.window != window) {
window.top.location = "/login-main.action";
}
}

问题2:

因为Shiro会记录上一次造成会话超时的页面,登录成功后,会直接跳转到这个页面,而我这里是层级显示,所以,如果使用Shiro的跳转,则跳转的页面,将没有log和菜单栏了


解决方法:

1、重写登录的过滤器,将Shiro记录的页面清除并保存到自己定义的session中,完成跳转。

2、在首页,将自定义保存的请求取出跳转。

过滤器:

package cn.zfcr.shiro.filter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.SavedRequest;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.stereotype.Service;

/**
文件名:FormAuthenticationFilter.java
类说明: Shiro 表单验证过滤器扩展 写入登录验证失败的错误提示
作者:章锋
邮箱: zhangfeng2124@163.com
日期:2017年6月22日 下午2:29:54
描述:例:章锋-认证
版本:1.0
*/
@Service
public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.FormAuthenticationFilter {

public static final String DEFAULT_MESSAGE_PARAM = "message";

/** 自定义保存到session中的请求数据的key 用于页面跳转 */
public static final String CUSTOM_SAVED_REQUEST = "customSavedRequest";

private String messageParam = DEFAULT_MESSAGE_PARAM;

@Override
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
ServletResponse response) throws Exception {
SavedRequest savedRequest = WebUtils.getAndClearSavedRequest(request);
Session session = subject.getSession();
session.setAttribute(CUSTOM_SAVED_REQUEST, savedRequest);
return super.onLoginSuccess(token, subject, request, response);
}

/**
* 登录失败调用事件
*/
@Override
protected boolean onLoginFailure(AuthenticationToken token,
AuthenticationException e, ServletRequest request, ServletResponse response) {
String className = e.getClass().getName(), message = "";
if (IncorrectCredentialsException.class.getName().equals(className)
|| UnknownAccountException.class.getName().equals(className)){
message = "用户名或密码错误, 请重试.";
}
else if (e.getMessage() != null && StringUtils.startsWith(e.getMessage(), "msg:")){
message = StringUtils.replace(e.getMessage(), "msg:", "");
}
else{
message = "系统异常,请稍后再试!";
e.printStackTrace();
}
request.setAttribute(getFailureKeyAttribute(), className);
request.setAttribute(getMessageParam(), message);
return true;
}

public String getMessageParam() {
return messageParam;
}
}

首页跳转代码:

<s:if test="#session.customSavedRequest != null">
<script type="text/javascript">
var url = '${session.customSavedRequest.requestURI}?${session.customSavedRequest.queryString}';
$("#mainFrame").attr("src", url);
</script>
</s:if>

ok。