由于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整合进去,总是有错,想看看你是怎么配置的。