web-dev-qa-db-ja.com

SpringブートがグローバルCORSサポートの問題を有効にする:GETのみが機能し、POST、PUT、およびDeleteが機能しない

更新:1年以上後を振り返って、私は他の誰かを助ける更新の希望を与えています。

Spring IO通常のユーザーがブラウザで処理できるリクエストには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.
               }

フィルターと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も同様に機能しません。私は非常に混乱しています。

24
Half Ass Dev

私は同じ問題を抱えていました-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

8
iharel

私は同様の問題を抱えていました、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");
            }
        };
    }
}
6
Charles

allowedOriginsメソッドを.allowedOrigins("*")に変更してみてください。 Postmanは拡張機能であり、別の「ホスト」で実行されます。

ただし、影響を必ず理解してください。 https://spring.io/understanding/CORS

5
Bruno

同様の問題があり、問題を解決するにはコントローラーの@CrossOriginを削除する必要があることがわかりました。しかし、それがなぜ「無効なCORSリクエスト」を引き起こしているのかを理解することはできません。

1
Krisrettiwt

私は同じ問題に直面し、私が見つけたものを調査した後、ブラウザは応答でAccess-Control-Allow-Originという名前のHTTPヘッダーを探します。

ブラウザはOPTION requestを送信して、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);
    }
}

0
Joginder Malik