Spring Security会话超时AJAX处理
SpringSecurity版本:2.0.5
应用场景:
用户登录系统,进行录入操作,长时间未保存,当会话超时后,用户进行保存(通过AJAX请求),系统提示“会话超时请重新登录”。
SpringSecurity目前的行为:
SpringSecurity实际上是把这种请求当成未登录的请求,并抛出不允许访问的异常(org.springframework.security.AccessDeniedException),然后请求重定向到登录页面。
相关的方法有:
org.springframework.security.ui.ExceptionTranslationFilter.doFilterHttp(HttpServletRequest, HttpServletResponse, FilterChain) org.springframework.security.ui.ExceptionTranslationFilter.handleException(ServletRequest, ServletResponse, FilterChain, SpringSecurityException) org.springframework.security.ui.ExceptionTranslationFilter.sendStartAuthentication(ServletRequest, ServletResponse, FilterChain, AuthenticationException) org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint.commence(ServletRequest, ServletResponse, AuthenticationException)
见org.springframework.security.ui.ExceptionTranslationFilter.handleException(ServletRequest,ServletResponse,FilterChain,SpringSecurityException)中:
if (exception instanceof AuthenticationException) { if (logger.isDebugEnabled()) { logger.debug("Authentication exception occurred; redirecting to authentication entry point", exception); } sendStartAuthentication(request, response, chain, (AuthenticationException) exception); } else if (exception instanceof AccessDeniedException) { if (authenticationTrustResolver.isAnonymous(SecurityContextHolder.getContext().getAuthentication())) { if (logger.isDebugEnabled()) { logger.debug("Access is denied (user is anonymous); redirecting to authentication entry point", exception); } sendStartAuthentication(request, response, chain, new InsufficientAuthenticationException("Full authentication is required to access this resource"));//在这里重定向到登录页面 } else { if (logger.isDebugEnabled()) { logger.debug("Access is denied (user is not anonymous); delegating to AccessDeniedHandler", exception); } accessDeniedHandler.handle(request, response, (AccessDeniedException) exception); } }
正常来说应该要重写org.springframework.security.ui.ExceptionTranslationFilter.handleException方法,加入相应的逻辑(判断是否为AJAX请求并作出对应的处理),但由于handleException为私有方法,不能直接对其进行扩展,所以只能寻找其它扩展方式了。
可以选择重写org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint.commence,这个方法的作用是执行重定向到登录页面,我们可以简单的认为当请求为AJAX时即是会话超时的场景,当然再严谨一点,比如异常的类型与消息,代码如下:
public void commence(ServletRequest request, ServletResponse response, AuthenticationException authException) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest)request; if ("XMLHttpRequest".equals(httpRequest.getHeader("X-Requested-With"))){ Map<String, Object> error = new HashMap<String, Object>(); error.put("success", false); error.put("code", "001"); error.put("message", "与服务器的会话已经超时"); error.put("data", ""); // 兼容extjs form loading RenderUtils.renderJSON((HttpServletResponse)response, error); } else super.commence(request, response, authException); }
... <http entry-point-ref="authenticationProcessingFilterEntryPoint"> ...
相关推荐
结束数据方法的参数,该如何定义?-- 集合为自定义实体类中的结合属性,有几个实体类,改变下标就行了。<input id="add" type="button" value="新增visitor&quo