日期:2014-05-16  浏览次数:20540 次

SSH+ExtJS项目,当session过期时跳转到登陆界面
由于ExtJS项目,在页面发送请求都是以Ajax这种形式的异步请求,所以当后台检测到session过期时,不能通过转发使客户端跳转到login页面。http://jayklin.iteye.com/blog/1039132

在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,详情见:http://jayklin.iteye.com/blog/1039145

到目前为止,已经实现了后台检测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";
			}
		});
1 楼 fanfubao 2012-05-25  
博主有SSH2+Extjs+spring security的源码吗?我整合的好久,也没把spring security整合进去,总是有错,想看看你是怎么配置