Spring Boot-CORS过滤器适用于GET,但不适用于其他HTTP动词

问题描述:

我正在使用Angular 9前端的Spring Boot 2.2.5应用程序.

I am working in a Spring Boot 2.2.5 application with an Angular 9 frontend.

我一直在尝试在Spring Boot后端上配置CORS过滤器,以允许任何来源的任何请求的任何标头.

I have been trying to configure a CORS filter on the Spring Boot backend to allow any origin with any headers for any request.

根据我的研究,我目前在主 Application.java 文件中实现的功能应该可以正常工作

Based on my research, what I currently have implemented in my main Application.java file should work:

@Bean
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("OPTIONS");
    config.addAllowedMethod("GET");
    config.addAllowedMethod("POST");
    config.addAllowedMethod("PUT");
    config.addAllowedMethod("DELETE");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

但是,我遇到的是,这只允许我执行从前端到后端控制器的 GET 调用.对 POST PUT 的任何其他调用均失败,并出现以下错误:

However, what I am experiencing is that this is only allowing me to execute GET call from the frontend to my controller on the backend. Any other call to POST or PUT fails with the following error:

Access to XMLHttpRequest at 'http://localhost:8080/spring-boot-starter-seed/default-theme/save/cyan' from origin 'http://localhost:8083' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

我在某种程度上了解即时消息,因为如果删除实现的 @Bean ,则从前端到后端的所有调用都会由于该错误而失败.但是在实现该Bean时,由于某种原因,它仅适用于 GET 请求.

I know im somewhat on the right track because if I remove the @Bean I implemented, then all calls from frontend to backend fail due to that error. But when implementing that Bean, for some reason its only working for GET requests.

有什么我想念的吗?

*****更新*****

***** Update *****

我不知道这是否会有所帮助,但是,我正在使用Azure AD对此应用程序进行身份验证.我有一个看起来像这样的 WebSecurityConfig :

I dont know if this will be helpful, but, I am using Azure AD for authentication with this application. I have a WebSecurityConfig that looks like this:

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public JwtAuthenticationConverter jwtAuthenticationConverter() {
        JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
        grantedAuthoritiesConverter.setAuthoritiesClaimName("roles");
        grantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");

        JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
        return jwtAuthenticationConverter;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/actuator/**", "/heartbeat/**", "/register", "/unregister").permitAll()
                .anyRequest().authenticated()
                .and()
                .oauth2ResourceServer()
                .jwt()
                .jwtAuthenticationConverter(this.jwtAuthenticationConverter());
    }
}

在我以前的帖子中,我说过 GET 请求正在工作,但这似乎有些虚假.

Earlier in my post I said that GET requests are working, but that seems to be somewhat false.

GET/heartbeat 有效.但是...

GET/default-theme 不起作用,并且失败,并出现相同的无访问权限-允许-起源"错误.

GET /default-theme does not work and fails with the same No Access-Control-Allow-Origin error.

这两个Controller路径之间的唯一区别是/default-theme 不包含在排除的antMatchers中,并且受 @PreAuthorize(value ="hasRole('ROLE_access')')

The only difference between these two Controller paths is that the /default-theme is not included in the excluded antMatchers, and it is protected by @PreAuthorize(value = "hasRole('ROLE_access')")

因此,事实证明,我对原始帖子的更新处于正确的轨道上,假定Spring Security和我的 WebSecurityConfig 是原因的一部分.

So, as it turns out, my update on my original post was on the right track to assume that Spring Security and my WebSecurityConfig was part of the cause.

我在答案这里.

我需要更新我的 HttpSecurity 配置,使其首先包含 .cors():

I needed to update my HttpSecurity config to include the .cors() first:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().and()
            .authorizeRequests()
            .antMatchers("/actuator/**", "/heartbeat", "/register", "/unregister").permitAll()
            .anyRequest().authenticated()
            .and()
            .oauth2ResourceServer()
            .jwt()
            .jwtAuthenticationConverter(this.jwtAuthenticationConverter());
}

完成此操作后,所有其他CORS配置都是不必要的,可以将其从我的应用中删除.只需将 @CrossOrigin 批注添加到任何相关的控制器中即可.

After doing this, all other CORS configurations were unnecessary and could be removed from my app. Just add the @CrossOrigin annotation to any relevant controllers.

在此位置上,调用我的 GET/default-theme 控制器,该控制器受 @PreAuthorize(value =" hasRole('ROLE_access')")保护,摆脱了No Access-Control-Allow-Origin错误,并导致了我所期望的错误,它是401响应.

With this in place, calling my GET /default-theme controller, protected by the @PreAuthorize(value = "hasRole('ROLE_access')"), got rid of the No Access-Control-Allow-Origin error, and resulted in the error I expected which was a 401 response.

所有这些的根本原因是因为我受命将这个应用程序从LDAP身份验证迁移到Azure AD身份验证.

The underlying reason for all of this was because I was tasked with migrating this application from LDAP auth to Azure AD auth.

希望这会在将来对某人有所帮助.

Hopefully this will help someone in the future.