会话过期时重定向

时间:2015-11-03 15:57:50

标签: ajax jsf primefaces spring-security

当ajax或非ajax事件发生且会话过期时,我使用了多种方法之一来解决重定向到登录页面的问题:https://gist.github.com/banterCZ/5160269

在调试模式下测试ajax情况时,我执行了以下步骤:

  1. 在浏览器中打开两个标签页。
  2. 执行登录。
  3. 第一页显示数据表,其中包含多个操作按钮。
  4. 第二页显示退出按钮。
  5. 所以,当我按下注销按钮时,我将进入JsfRedirectStrategy类进入else语句:
  6. 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;
        }
    
    }
    

0 个答案:

没有答案