Spring boot enable Global CORS支持问题:仅GET有效,POST,PUT和Delete不起作用

问题描述 投票:24回答:5

更新:现在回想了一年多以后,我给出了希望能对其他人有所帮助的最新消息。

Spring IO建议对普通用户可能由浏览器处理的任何请求使用CSRF保护。如果仅创建非浏览器客户端使用的服务,则可能需要禁用CSRF保护。由于我的应用程序是API,并且将由浏览器处理,因此禁用CSRF并不是一种方法。

默认情况下,Spring Boot启用了CSRF,您需要添加以下代码以添加CSRF存储库,并需要添加过滤器以将CSRF令牌添加至您的http请求。 (解决方案来自这里Invalid CSRF Token in POST request

@Override
protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/assets/**", "/templates/**", "/custom-fonts/**", "/api/profile/**", "/h2/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .logoutSuccessUrl("/login?logout")
                .permitAll()
                .and()
            .csrf().csrfTokenRepository(csrfTokenRepository())
                .and()
            .addFilterAfter(csrfHeaderFilter(), SessionManagementFilter.class); // Register csrf filter.
               }

过滤器和CsrfToken存储库部分:

private Filter csrfHeaderFilter() {
    return new OncePerRequestFilter() {

        @Override
        protected void doFilterInternal(HttpServletRequest request,
                                        HttpServletResponse response,
                                        FilterChain filterChain) throws ServletException, IOException {

            CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
            if (csrf != null) {
                Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
                String token = csrf.getToken();
                if (cookie == null || token != null
                        && !token.equals(cookie.getValue())) {

                    // Token is being added to the XSRF-TOKEN cookie.
                    cookie = new Cookie("XSRF-TOKEN", token);
                    cookie.setPath("/");
                    response.addCookie(cookie);
                }
            }
            filterChain.doFilter(request, response);
        }
    };
}   


private CsrfTokenRepository csrfTokenRepository() {
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
        repository.setHeaderName("X-XSRF-TOKEN");
        return repository;
    }

我在2016年2月问的原始问题

我正在为Spring 4提供Spring-boot RESTful API的Global CORS支持。

我正在关注官方的Spring Boot Doc(https://spring.io/guides/gs/rest-service-cors/),并将其添加到我的应用程序中:

public class SomeApiApplication {

    public static void main(String[] args) {
        SpringApplication.run(SomeApiApplication.class, args);
    }


    //Enable Global CORS support for the application
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedOrigins("http://localhost:8080")
                        .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD")
                        .allowedHeaders("header1", "header2") //What is this for?
                        .allowCredentials(true);
            }
        };
    }
}

我不明白为什么只有GET可以工作,对于其余的HTTP调用,我收到一条错误消息,内容为“无效的CORS请求”。我会错过任何设置吗?如果我的设置不正确,则GET也不能正常工作。我很困惑

java spring spring-mvc cors
5个回答
8
投票

我有同样的问题-GET正常工作。 POST没有。我在CORS域中寻找答案,但最终发现这是由于CSRF保护所致。为了解决这个问题,我在安全配置中禁用了CSRF保护:

@Configuration @EnableWebSecurity
    public class SpringWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                **.csrf().disable()** //TODO: for production, must be reconfigured in order to disable only in specific cases. This line was added because without it, HTTP POST requests did not work. 
                .authorizeRequests()
                    .antMatchers("/api/**").permitAll()
                    .anyRequest().authenticated()
                    .and()
                .formLogin()
                    .loginPage("/login")
                    .permitAll()
                    .and()
                .logout()
                    .permitAll();
        }

确保您了解自己在做什么:https://docs.spring.io/spring-security/site/docs/current/reference/html/web-app-security.html#csrf


6
投票

我有一个类似的问题,只有HEAD GET和POST为我工作。我发现addCorsMappings的默认值为addCorsMappings

此代码对我有用:

allowedMethods

5
投票

尝试将allowedMethods方法更改为import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class MyConfiguration { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurerAdapter() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedMethods("*") .allowedOrigins("http://localhost:4200"); } }; } } 。邮递员是一个扩展,它在另一个“主机”中运行。

但是请确保您了解影响:allowedOrigins


1
投票

我有类似的问题,并发现必须删除控制器上的@CrossOrigin才能解决该问题。还没有弄清楚为什么这会导致“无效的CORS请求”。


0
投票

我遇到了同样的问题,经过研究发现,浏览器在响应中查找名为Access-Control-Allow-Origin的HTTP标头。

浏览器发送一个OPTION request,以找出允许使用诸如PUTs,DELETE之类的方法。如果从服务器端允许了所请求的方法,则浏览器将发出实际请求,并再次根据响应中的Access-Control-Allow-Origin标头传递或阻止响应。只需添加一个四季豆,即可解决您的问题。

.allowedOrigins("*")
© www.soinside.com 2019 - 2024. All rights reserved.