簡體   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