当ajax或非ajax事件发生且会话过期时,我使用了多种方法之一来解决重定向到登录页面的问题:https://gist.github.com/banterCZ/5160269
在调试模式下测试ajax情况时,我执行了以下步骤:
Bean:
@Component
public class JsfRedirectStrategy implements InvalidSessionStrategy {
final static Logger logger = LoggerFactory.getLogger(JsfRedirectStrategy.class);
private static final String FACES_REQUEST_HEADER = "faces-request";
private String invalidSessionUrl = "/login.xhtml";
@Override
public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
boolean ajaxRedirect = "partial/ajax".equals(request.getHeader(FACES_REQUEST_HEADER));
if (ajaxRedirect) {
String contextPath = request.getContextPath();
String redirectUrl = contextPath + invalidSessionUrl;
logger.debug("Session expired due to ajax request, redirecting to '{}'", redirectUrl);
String ajaxRedirectXml = createAjaxRedirectXml(redirectUrl);
logger.debug("Ajax partial response to redirect: {}", ajaxRedirectXml);
response.setContentType("text/xml");
response.getWriter().write(ajaxRedirectXml);
} else {
String requestURI = getRequestUrl(request);
logger.info(
"Session expired due to non-ajax request, starting a new session and redirect to requested url '{}'",
requestURI);
request.getSession(true);
response.sendRedirect(requestURI);
}
}
private String getRequestUrl(HttpServletRequest request) {
StringBuffer requestURL = request.getRequestURL();
String queryString = request.getQueryString();
if (StringUtils.hasText(queryString)) {
requestURL.append("?").append(queryString);
}
return requestURL.toString();
}
private String createAjaxRedirectXml(String redirectUrl) {
return new StringBuilder().append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
.append("<partial-response><redirect url=\"")
.append(redirectUrl)
.append("\"></redirect></partial-response>").toString();
}
}
并打印以下消息: 会话由于非ajax请求而过期,启动新会话并重定向到请求的网址
因此,新会话已打开,即使用户已注销。
6。然后我将转到第一页并按下某个操作按钮以触发ajax事件,但没有任何操作(无操作。)
打印以下消息: osbaaudit.listener.AuditListener - AuditEvent [timestamp = Tue Nov 03 17:44:39 EET 2015,principal = anonymousUser,type = AUTHORIZATION_FAILURE,data = {type = org.springframework.security.access.AccessDeniedException,message =访问被拒绝}]
我认为这种行为的原因是在第5步执行此代码示例:
request.getSession(true);
从我的观点来看,正确的行为是第6步的结果会重定向到登录页面。
那么,请告诉我如何实现这一目标?
我的Spring Security配置是:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/invite.xhtml").permitAll()
.antMatchers("/login.xhtml").permitAll()
.antMatchers("/forgotpassword.xhtml").permitAll()
.antMatchers("/resetpwd.xhtml").permitAll()
.antMatchers("/admin/*").hasRole(Roles.ROLE_ADMIN.getSpringSecName())
.antMatchers("/**").authenticated()
.antMatchers("/actuator/*").permitAll()
.and()
.formLogin()
.loginPage("/login.xhtml").permitAll()
//.failureUrl("/login?error").permitAll()
.and()
.logout()
.logoutRequestMatcher( new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login.xhtml")
.permitAll()
.and()
.exceptionHandling().authenticationEntryPoint(new AjaxAwareAuthenticationEntryPoint("/login.xhtml"));
http.headers().frameOptions().disable();
http.addFilterBefore(sessionManagementFilter(), FilterSecurityInterceptor.class);
// @formatter:on
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/javax.faces.resource/**");
}
@Bean
public HttpSessionSecurityContextRepository httpSessionSecurityContextRepository() {
return new HttpSessionSecurityContextRepository();
}
@Bean
public JsfRedirectStrategy jsfRedirectStrategy() {
return new JsfRedirectStrategy();
}
@Bean
public SessionManagementFilter sessionManagementFilter() {
SessionManagementFilter sessionManagementFilter = new SessionManagementFilter(
httpSessionSecurityContextRepository());
sessionManagementFilter.setInvalidSessionStrategy(jsfRedirectStrategy());
return sessionManagementFilter;
}
}