首页 > 解决方案 > Spring Boot - CORS 过滤器适用于 GET,但不适用于其他 HTTP 动词

问题描述

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

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

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

@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从前端到后端控制器的调用。任何其他调用POSTPUT失败并出现以下错误:

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请求。

有什么我错过的吗?

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

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

@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请求正在起作用,但这似乎有些错误。

GET /heartbeat作品。然而...

GET /default-theme不起作用并失败并出现相同的 No Access-Control-Allow-Origin 错误。

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

标签: javaangularspringspring-bootcors

解决方案


我认为这里的问题是由于调度程序 servlet 的过滤器:

试试这个类来实现一个过滤器:

public class CORSFilter extends GenericFilterBean implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chaine)
            throws IOException, ServletException {
        HttpServletResponse httpResponse = (HttpServletResponse)response;
        httpResponse.setHeader("Access-Control-Allow-Origin", "*");
        httpResponse.setHeader("Access-Control-Allow-Methods", "*");
        httpResponse.setHeader("Access-Control-Allow-Headers", "*");
        httpResponse.setHeader("Access-Control-Allow-Credentials", "false");
        httpResponse.setHeader("Access-Control-Max-Age", "3600");
        System.out.println("****************** CORS Configuration Completed *******************");
        chaine.doFilter(request, response);
    }

}

然后将 bean 注入您的主应用程序类或任何地方:

@Bean
    public FilterRegistrationBean crosFilterRegistration(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean(new CORSFilter());
        registrationBean.setName("CORS Filter");
        registrationBean.addUrlPatterns("/*");
        registrationBean.setOrder(1);
        return registrationBean;
    }

希望这会有所帮助


推荐阅读