【问题标题】:Spring boot enable Global CORS support issue: only GET is working, POST, PUT and Delete are not workingSpring Boot 启用全局 CORS 支持问题:只有 GET 有效,POST、PUT 和 Delete 无效
【发布时间】:2016-05-20 19:09:27
【问题描述】:

更新: 现在回顾一年多后,我给出了一个更新希望能帮助别人。

Spring IO 建议对普通用户可以通过浏览器处理的任何请求使用 CSRF 保护。如果您只创建非浏览器客户端使用的服务,您可能希望禁用 CSRF 保护。 由于我的应用是一个 API,会被浏览器处理,所以禁用 CSRF 不是一种方法。

默认情况下,CSRF 在 Spring Boot 中启用,您需要添加以下代码以添加 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.
               }

filter & CsrfToken Repository 部分:

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 提供全球 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 也不应该工作。我很困惑。

【问题讨论】:

  • 尝试发布 XML 配置
  • 我正在使用 POSTMAN 进行测试。对于我的请求标头,我有授权和内容类型。我想知道我是否需要为 CORS 放一些额外的标题?
  • @Abdelhak:我使用的是 Spring 4,我的代码中不应包含任何 XML。
  • 我必须手动指定所有方法都被允许(包括删除和补丁之前未能通过 CORS 协商) - 省略 .allowedMethods 调用不会自动添加所有方法!

标签: java spring spring-mvc cors


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    我有同样的问题 - 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

    【讨论】:

      【解决方案3】:

      尝试将allowedOrigins 方法更改为.allowedOrigins("*")。 Postman 是一个扩展,它在另一个“主机”中运行。

      但请确保您了解影响:https://spring.io/understanding/CORS

      【讨论】:

        【解决方案4】:

        我遇到了类似的问题,只有 HEAD GET 和 POST 对我有用。 我发现addCorsMappings 的默认值为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");
                    }
                };
            }
        }
        

        【讨论】:

        • PUT 方法不支持我。我添加了 allowedMethods("*");然后它起作用了。
        【解决方案5】:

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

        浏览器发送一个OPTION 请求 来找出允许使用PUTs、DELETE 等方法。如果服务器端允许请求的方法,则浏览器将发出实际请求,再次根据响应中的 Access-Control-Allow-Origin 标头传递或阻止响应。 只需添加一个spring bean,即可解决您的问题。

        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.web.cors.CorsConfiguration;
        import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
        import org.springframework.web.filter.CorsFilter;
        @Configuration
        public class RestConfig {
            @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);
            }
        }
        
        

        【讨论】:

          【解决方案6】:

          这是我的SecurityConfig.java。我不得不在这篇文章中混合各种答案才能让它对我有用。

          @Configuration
          public class SecurityConfig extends WebSecurityConfigurerAdapter {
          
              @Override
              protected void configure(HttpSecurity http) throws Exception {
                  http.authorizeRequests().antMatchers("/").permitAll();
                  // unblock post, put and delete requests
                  http.csrf().disable();
                  // enable cors
                  http.cors();
              }
          
              @Bean
              CorsConfigurationSource corsConfigurationSource() {
                  CorsConfiguration configuration = new CorsConfiguration();
                  configuration.setAllowCredentials(true);
                  configuration.addAllowedOrigin("http://localhost:3000");
                  configuration.addAllowedHeader("*");
                  configuration.addAllowedMethod("*");
                  UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
                  source.registerCorsConfiguration("/**", configuration);
                  return source;
              }
          }
          

          如果您想允许所有来源,请将http://localhost:3000 替换为*

          【讨论】:

            【解决方案7】:

            三重检查您的路径名是否在后端/前端应用程序以及任何路径变量等之间对齐。如果合同不正确,OPTIONS 将返回 403,因为它找不到要使用的正确 API。看起来像是浏览器中的 CORS 问题,但根本原因是合同不同。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-08-09
              • 2018-05-23
              • 2020-02-06
              • 2023-03-14
              • 1970-01-01
              • 2019-01-14
              • 2017-03-19
              • 2020-07-11
              相关资源
              最近更新 更多