【问题标题】:Spring Security Logout doesn't work with Spring 4 CORSSpring Security Logout 不适用于 Spring 4 CORS
【发布时间】:2016-03-13 07:17:14
【问题描述】:

最近我在 Spring 4 中尝试了新的内置 CORS-Support。这个功能很棒,我想在我的 Spring Boot / AngularJS 应用程序中实现它。

所有请求都可以正常工作,但我无法注销我的用户,因为OPTIONS-对/logout 的请求由Spring Security 处理。

是否可以在 Spring Security 之前处理 OPTIONS-Request 或者我应该在 LogoutSuccessHandler 中附加 CORS-Headers

【问题讨论】:

    标签: java angularjs spring spring-mvc spring-security


    【解决方案1】:

    我知道这有点晚了。由于 /logout 响应中未返回 CORS 标头 Access-Control-Allow-Origin,因此 /logout 被我的 Angular2 浏览器应用程序拒绝,我遇到了同样的问题。 /logout 似乎在到达 CORS 过滤器之前已处理,因此没有获取标题。我尝试了上面的解决方案,但它对我不起作用。所以,我尝试了下一个解决方案,效果很好:

    • 创建LogoutHandler实现类并实现logout()
    • 创建LogoutSuccessHandler实现类,实现onLogoutSuccess()
    • 将这两个类连接到 Spring 安全配置

    原来我不需要 LogoutSuccessHandler 类,只需要 LogoutHandler。 LogoutSuccessHandler(未显示)只是一个带有日志记录语句的空实现。 LogoutHandler 如下。这是一个用 Groovy 编码的 Spring-boot REST 应用程序的 sn-p(非常类似于 java)

    @Slf4j
    class TodosLogoutHandler implements LogoutHandler {
    
    /**
     * For some reason the spring-session logout gets processed before the request
     * reaches the CORS filter so the response doesn't get the allow-origin header
     * which then causes the browser to reject the logout response. I tried a bunch
     * of other methods of trying to include /logout to the CORS filter but they
     * didn't work so figured a logout handler would be a place I could manually
     * set the header to persuade the browser to accept the response - it worked!!
     * @param request
     * @param response
     * @param authentication
     */
      @Override
      void logout(
            HttpServletRequest request,
            HttpServletResponse response,
            Authentication authentication) {
    
        response.setHeader("Access-Control-Allow-Origin", "*")
    
        log.info("TodosLogoutHandler logging you out of the back-end app.")
      }
    }
    

    然后将其连接到扩展 WebSecurityConfigurerAdapter 的安全配置类中,如下所示。最后一部分,显示注销部分是标准 configure() 方法中的相关部分。

        @Override
      public void configure(HttpSecurity http) throws Exception {
    
        http.authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()                 // Allow any CORS OPTIONS calls
                .antMatchers(HttpMethod.GET, "/priority", "/status").permitAll()    // Allow all ref data
                .anyRequest().authenticated()
                .and()
                    .csrf().disable()
                    .httpBasic().realmName("Spring REST Todos")
                .and()
                    // Custom logout handler only exists to handle a CORS problem with /logout
                    // where spring-session processes the logout request/response before it gets
                    // to the CORS filter so it doesn't get the allow-origin header which  then
                    // causes the browser to reject the /logout response. Manually set the
                    // allow-origin header in the logout handler and Bob's your uncle.
                    .logout()
                    .logoutUrl("/logout")
                    .logoutSuccessHandler(new TodosLogoutSuccessHandler())
                    .addLogoutHandler(new TodosLogoutHandler())
                    .invalidateHttpSession(true)
    }
    

    【讨论】:

      【解决方案2】:

      使用 Spring Security 时,建议使用CorsFilter。您需要确保在 Spring Security 的 FilterChainProxy 之前订购 CorsFilter

      您可以参考Spring Data Rest and Cors了解使用CorsFilter的详细信息。对于这个问题,不同之处在于您可能只想注册注销 URL。例如:

      @Bean
      public CorsFilter corsFilter() {
      
          UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
          CorsConfiguration config = new CorsConfiguration();
          config.setAllowCredentials(true); // you USUALLY want this
          // likely you should limit this to specific origins
          config.addAllowedOrigin("*"); 
          config.addAllowedHeader("*");
          config.addAllowedMethod("GET");
          config.addAllowedMethod("POST");
          config.addAllowedMethod("PUT");
          source.registerCorsConfiguration("/logout", config);
          return new CorsFilter(source);
      }
      

      【讨论】:

        猜你喜欢
        • 2016-04-16
        • 2018-08-26
        • 2016-02-17
        • 2017-10-30
        • 2017-06-09
        • 2014-11-29
        • 2021-03-25
        • 2015-11-03
        • 2015-10-02
        相关资源
        最近更新 更多