Spring 数据 REST 中的 CORS 预检请求

CORS preflight request in Spring Data REST

我有一个 Spring Boot / Spring Data REST 服务允许访问许多资源。其中一些资源(例如 /detections)可以免费访问,其他资源(例如 /users)需要基本的 HTTP 身份验证。通过使用 CURL 测试 REST 服务,一切都按预期工作。当我尝试从 Angular2 网络应用程序访问服务时出现问题。

在这种情况下,我在访问不受保护的资源时没有问题http://api.mydomain.com/detections :

this.http.get(this.DETECTIONS_API_ENDPOINT).subscribe(
                            response => {
                              ...
                            },
                            error => {
                              ...
                            }
                    );

但是,如果我尝试通过使用正确的用户名和密码传递所需的 headers 来访问受保护的资源 http://api.mydomain.com/users

    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    headers.append('Authorization', 'Basic ' + btoa(username+':'+password)); 

    return this.http.get(this.USERS_API_ENDPOINT, { body: "", headers: headers }).subscribe(
                            response => {
                              ...
                            },
                            error => {
                              ...
                            }
                    );

我(在 Firefox 控制台中)收到一条错误消息,上面写着 cross-origin request blocked... Reason: CORS preflight request unsuccessfull(请注意,这是我从意大利语翻译过来的。我找不到准确对应的英文错误消息。唯一的区别是在第二种情况下,两次调用似乎是 headers 的传递,这会触发发送 OPTIONS 而不是 GET 请求。

这是我的 spring 安全配置:

@Configuration
public class MyAppConfigurationSecurity extends WebSecurityConfigurerAdapter {

    private Md5PasswordEncoder md5PasswordEncoder = new Md5PasswordEncoder();

    @Autowired
    private UserDetailsService myAppUserService;

    /**
     * HttpSecurity URL configuration settings. Configure authentication necessary for POST but not for GET
     */

    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        http.csrf().disable()
            .authorizeRequests()
                .antMatchers(HttpMethod.GET, "/detections").permitAll()
                .antMatchers(HttpMethod.GET, "/detections/search/findTop5ByOrderByTimestampDesc").permitAll()
                .antMatchers("/users").hasAuthority("ADMIN")
                .antMatchers("/roles").hasAuthority("ADMIN")
                .antMatchers("**").authenticated()
            .and().httpBasic().and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }


    /**
     * Sets custom MyAppUserService bean as user detail service
     */

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myAppUserService).passwordEncoder(md5PasswordEncoder);
    }

}

这是CORS过滤器配置;我按照 的建议添加了这个 class,它最初解决了我的 CORS-access 访问未受保护资源的问题。不幸的是,它似乎在受保护资源的情况下不起作用:

@Configuration
public class MyAppConfigurationCors {

    @Bean
    public CorsFilter corsFilter() {

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true); // you USUALLY want this
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("OPTIONS"); // I added this in a second phase, but nothing changes
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

请参阅Spring文档了解如何集成CORS and Spring Security

必须先处理 CORS:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // by default uses a Bean by the name of corsConfigurationSource
            .cors().and()
            ...
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

您可以在第一个 Spring 安全过滤器之前添加 cors 过滤器,即 ChannelProcessingFilter。下面的一段代码将有助于解释更多。

protected void configure(HttpSecurity http) throws Exception {
 http.requiresChannel().antMatchers("/*").requires(ANY_CHANNEL).and()
.authorizeRequests().antMatchers("/api/customer/**").permitAll()
.antMatchers("/api/signin").permitAll()
.antMatchers("/api/**").permitAll()
.antMatchers("/**").permitAll().and()
.addFilterBefore(corsFilter(), ChannelProcessingFilter.class)
.and().csrf().disable();
} 

如果需要任何其他信息,请访问此 -: http://javamusings.com/enabling-cors-support-in-spring-framework/。 注-:我是post的作者。