由于ExtJS项目,在页面发送请求都是以Ajax这种形式的异步请求,所以当后台检测到session过期时,不能通过转发使客户端跳转到login页面。[url]http://jayklin.iteye.com/blog/1039132[/url]
在web.xml配置的Filter、Servlet等都是按照顺序拦截的,项目使用Spring Security作为用户登陆权限管理,所以所有正常操作的过滤器,必须配置在Security过滤器之后。
项目实现思路,在Security过滤器之前加入两个过滤器,一个是Struts2过滤器,但这个过滤器只对一个指定请求起作用,如处理session过期的action请求。令一个是实现Filter接口的自定义过滤器,实现对当前请求session状态的检测,如发现session已经过期,通过sendRedirect把请求转发给前面那个指定的Struts2过滤器,之后经过自定义的全局拦截器(继承AbstractInterceptor),向客户端发送session过期的信息。通过js检测,如果session过期后跳转页面到登陆界面。
具体实现代码:首先是定义检查session状态的Filter,这里使用Spring Security实现用户验证,这样的session当没有过期时可以通过属性名字“SPRING_SECURITY_CONTEXT”获得SecurityContext实例,如
因为该Filter在web.xml中配置url-pattern通配符为“/*”,这样所有请求都会经过该Filter,但这里这需要检验ExtJS发出的"**_**"这样格式的Ajax请求,所以需要首先判断请求是否为Ajax请求;当securityContext == null时,说明session已经过期,这时跳转到test_timeout。
在web.xml中,在上面这个Filter之前加入一个url-pattern通配符为“test_timeout”的Struts过滤器,如web.xml:
需要在session已过期的action请求响应前,向客户端发送session过期的信息,必须在Struts.xml文件中配置自定义的Interceptor,详情见:[url]http://jayklin.iteye.com/blog/1039145[/url]
到目前为止,已经实现了后台检测session状态,之后在action响应之前向客户端发送session已经过期的信息,那么需要在ExtJS中获取这个信息,实现页面跳转。在ExtJS中有两种请求:一为Ext.Ajax.request,另一个为Ext.form.Action.submit。但是经过我的测试,这两种请求在请求完成之后都会触发Ext.Ajax的“requestcomplete”事件,那么就可以在这里做出判断,如:
在web.xml配置的Filter、Servlet等都是按照顺序拦截的,项目使用Spring Security作为用户登陆权限管理,所以所有正常操作的过滤器,必须配置在Security过滤器之后。
项目实现思路,在Security过滤器之前加入两个过滤器,一个是Struts2过滤器,但这个过滤器只对一个指定请求起作用,如处理session过期的action请求。令一个是实现Filter接口的自定义过滤器,实现对当前请求session状态的检测,如发现session已经过期,通过sendRedirect把请求转发给前面那个指定的Struts2过滤器,之后经过自定义的全局拦截器(继承AbstractInterceptor),向客户端发送session过期的信息。通过js检测,如果session过期后跳转页面到登陆界面。
具体实现代码:首先是定义检查session状态的Filter,这里使用Spring Security实现用户验证,这样的session当没有过期时可以通过属性名字“SPRING_SECURITY_CONTEXT”获得SecurityContext实例,如
public class SessionTimeoutFilter implements Filter{
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest servletRequest = (HttpServletRequest)request;
HttpServletResponse servletResponse = (HttpServletResponse)response;
HttpSession session = servletRequest.getSession();
String url = servletRequest.getRequestURI();
String path = url.substring(url.lastIndexOf("/"));
String[] s = path.split("_");
if (url.indexOf(".")==-1 && s.length == 2) {
SecurityContext securityContext = (SecurityContext)session.getAttribute("SPRING_SECURITY_CONTEXT");
if (securityContext == null) {
servletResponse.sendRedirect(servletRequest.getContextPath()+"/test_timeout");
}else {
chain.doFilter(request, response);
}
}else {
chain.doFilter(request, response);
}
}
public void init(FilterConfig filterConfig) throws ServletException {
}
}
因为该Filter在web.xml中配置url-pattern通配符为“/*”,这样所有请求都会经过该Filter,但这里这需要检验ExtJS发出的"**_**"这样格式的Ajax请求,所以需要首先判断请求是否为Ajax请求;当securityContext == null时,说明session已经过期,这时跳转到test_timeout。
在web.xml中,在上面这个Filter之前加入一个url-pattern通配符为“test_timeout”的Struts过滤器,如web.xml:
<filter>
<filter-name>strutsForSessionTimeout</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>strutsForSessionTimeout</filter-name>
<url-pattern>/test_timeout</url-pattern>
</filter-mapping>
<filter>
<filter-name>SessionTimeoutFilter</filter-name>
<filter-class>com.edward.SessionTimeoutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SessionTimeoutFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
需要在session已过期的action请求响应前,向客户端发送session过期的信息,必须在Struts.xml文件中配置自定义的Interceptor,详情见:[url]http://jayklin.iteye.com/blog/1039145[/url]
到目前为止,已经实现了后台检测session状态,之后在action响应之前向客户端发送session已经过期的信息,那么需要在ExtJS中获取这个信息,实现页面跳转。在ExtJS中有两种请求:一为Ext.Ajax.request,另一个为Ext.form.Action.submit。但是经过我的测试,这两种请求在请求完成之后都会触发Ext.Ajax的“requestcomplete”事件,那么就可以在这里做出判断,如:
//session timeout
Ext.Ajax.on('requestcomplete', function(conn, response, options, e){
var s = response.responseText;
if(s.indexOf("{timeout:",0) != -1){
// window.location.reload();
window.location.href = "login.jsp?timeout=true";
}
});