Spring WebfluxとCORS

Spring WebfluxとCORS

1. 概要

previous postでは、クロスオリジンリソースシェアリング(CORS)仕様と、Spring内での使用方法について学習しました。

このクイックチュートリアルでは、we’ll set up a similar CORS configuration using Spring’s 5 WebFlux frameworkです。

まず、アノテーションベースのAPIでメカニズムを有効にする方法を見ていきます。

次に、グローバル構成として、または特別なWebFilterを使用して、プロジェクト全体でそれを有効にする方法を分析します。

2. 注釈付き要素でCORSを有効にする

Springは@CrossOriginアノテーションを提供して、コントローラークラスやハンドラーメソッドでCORSリクエストを有効にします。

2.1. リクエストハンドラメソッドで@CrossOriginを使用する

このアノテーションをマップされたリクエストメソッドに追加しましょう。

@CrossOrigin
@PutMapping("/cors-enabled-endpoint")
public Mono corsEnabledEndpoint() {
    // ...
}

WebTestClientを使用します(セクション「4」で説明したように)。 このエンドポイントから取得した応答を分析するためのthis post)のテスト:

ResponseSpec response = webTestClient.put()
  .uri("/cors-enabled-endpoint")
  .header("Origin", "http://any-origin.com")
  .exchange();

response.expectHeader()
  .valueEquals("Access-Control-Allow-Origin", "*");

さらに、プリフライトリクエストを試して、CORS設定が期待どおりに機能していることを確認できます。

ResponseSpec response = webTestClient.options()
  .uri("/cors-enabled-endpoint")
  .header("Origin", "http://any-origin.com")
  .header("Access-Control-Request-Method", "PUT")
  .exchange();

response.expectHeader()
  .valueEquals("Access-Control-Allow-Origin", "*");
response.expectHeader()
  .valueEquals("Access-Control-Allow-Methods", "PUT");
response.expectHeader()
  .exists("Access-Control-Max-Age");

@CrossOriginアノテーションには、次のデフォルト構成があります。

  • すべての発信元を許可します(応答ヘッダーの「*」値を説明します)

  • すべてのヘッダーを許可

  • ハンドラーメソッドによってマップされたすべてのHTTPメソッドが許可されます

  • 資格情報が有効になっていません

  • 「最大年齢」の値は1800秒(30分)です。

ただし、これらの値はいずれも、アノテーションのパラメータを使用して上書きできます。

2.2. コントローラで@CrossOriginを使用する

この注釈はクラスレベルでもサポートされており、すべてのメソッドに影響します。

クラスレベルの構成がすべてのメソッドに適していない場合は、両方の要素に注釈を付けて、目的の結果を得ることができます。

@CrossOrigin(value = { "http://allowed-origin.com" },
  allowedHeaders = { "example-Allowed" },
  maxAge = 900
)
@RestController
public class CorsOnClassController {

    @PutMapping("/cors-enabled-endpoint")
    public Mono corsEnabledEndpoint() {
        // ...
    }

    @CrossOrigin({ "http://another-allowed-origin.com" })
    @PutMapping("/endpoint-with-extra-origin-allowed")
    public Mono corsEnabledWithExtraAllowedOrigin() {
        // ...
    }

    // ...
}

3. グローバル構成でCORSを有効にする

WebFluxConfigurer実装のaddCorsMappings()メソッドをオーバーライドすることで、グローバルCORS構成を定義することもできます。

さらに、実装では、Spring WebFlux構成をインポートするために@EnableWebFluxアノテーションが必要です。

@Configuration
@EnableWebFlux
public class CorsGlobalConfiguration implements WebFluxConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry corsRegistry) {
        corsRegistry.addMapping("/**")
          .allowedOrigins("http://allowed-origin.com")
          .allowedMethods("PUT")
          .maxAge(3600);
    }
}

その結果、特定のパスパターンに対してクロスオリジンリクエスト処理を有効にしています。

デフォルトの構成は@CrossOriginの構成と似ていますが、許可されるのはGETHEAD、およびPOSTのメソッドのみです。

この構成をローカル構成と組み合わせることもできます。

  • 複数値属性の場合、結果のCORS構成は各仕様の追加になります

  • 一方、単一値の場合、ローカル値はグローバル値よりも優先されます

ただし、この方法を使用しても機能的なエンドポイントには効果的ではありません。

4. WebFilterでCORSを有効にする

機能エンドポイントでCORSを有効にする最良の方法は、WebFilterを使用することです。

in this postを確認したように、WebFiltersを使用して、エンドポイントの実装をそのままにしながら、リクエストとレスポンスを変更できます。

Springには、クロスオリジン構成を簡単に処理できるように、組み込みのCorsWebFilterが用意されています。

@Bean
CorsWebFilter corsWebFilter() {
    CorsConfiguration corsConfig = new CorsConfiguration();
    corsConfig.setAllowedOrigins(Arrays.asList("http://allowed-origin.com"));
    corsConfig.setMaxAge(8000L);
    corsConfig.addAllowedMethod("PUT");
    corsConfig.addAllowedHeader("example-Allowed");

    UrlBasedCorsConfigurationSource source =
      new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", corsConfig);

    return new CorsWebFilter(source);
}

これはアノテーション付きハンドラーにも効果的ですが、よりきめ細かい@CrossOrigin構成と組み合わせることはできません。

CorsConfigurationにはデフォルト設定がないことに注意する必要があります。

したがって、関連するすべての属性を指定しない限り、CORS実装はかなり制限されます。

デフォルト値を設定する簡単な方法は、オブジェクトでapplyPermitDefaultValues()メソッドを使用することです。

5. 結論

結論として、webfluxベースのサービスでCORSを有効にする方法の非常に短い例で学びました。

さまざまなアプローチを見てきました。したがって、今やらなければならないのは、どれが要件に最も適しているかを分析することです。

このトピックに関するほとんどのエッジケースを分析するテストケースとともに、our Github repoに多くの例を見つけることができます。