繁体   English   中英

Spring boot 启用全局 CORS 支持问题:只有 GET 有效,POST、PUT 和 Delete 无效

[英]Spring boot enable Global CORS support issue: only GET is working, POST, PUT and Delete are not working

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

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 提供全局 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 也不能正常工作。 我很困惑。

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

我有一个类似的问题,只有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");
            }
        };
    }
}

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

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

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

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

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);
    }
}

我有类似的问题,并发现我的控制器上的@CrossOrigin必须被删除才能解决问题。 然而要找出导致“无效的CORS请求”的原因。

这是我的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替换为*

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM