1. 概要

In any modern browser, Cross-Origin Resource Sharing (CORS) is a relevant specification with the emergence of HTML5 and JS clients that consume data via REST APIs.

多くの場合、JSにサービスを提供するホスト(例: example.com)は、データを提供するホストとは異なります(例: api.example.com)。 このような場合、CORSはクロスドメイン通信を可能にします。

SpringはCORSにファーストクラスのsupportを提供し、SpringまたはSpringBootWebアプリケーションで簡単かつ強力に構成する方法を提供します。

2. コントローラ方式のCORS設定

CORSの有効化は簡単です—アノテーション@CrossOriginを追加するだけです。

これは、いくつかの異なる方法で実装できます。

2.1. @RequestMappingの@CrossOriginアノテーション付きハンドラーメソッド

@RestController
@RequestMapping("/account")
public class AccountController {

    @CrossOrigin
    @RequestMapping(method = RequestMethod.GET, path = "/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

上記の例では、 retrieve()メソッドに対してのみCORSを有効にしました。 @CrossOrigin アノテーションの構成を設定していないことがわかります。そのため、デフォルトが使用されます。

  • すべての起源が許可されます。
  • 許可されるHTTPメソッドは、 @RequestMapping アノテーション(この例ではGET)で指定されたものです。
  • プリフライト応答がキャッシュされる時間( maxAge )は30分です。

2.2. コントローラの@CrossOrigin

@CrossOrigin(origins = "http://example.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {

    @RequestMapping(method = RequestMethod.GET, path = "/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

今回は、クラスレベルで@CrossOriginを追加しました。 したがって、 retrieve()メソッドと remove()メソッドの両方で有効になっています。 アノテーション属性の1つの値を指定することで構成をカスタマイズできます: origins methods allowedHeaders exposedHeaders 、[X182X ] allowCredentials 、またはmaxAge

2.3. @CrossOriginコントローラーおよびハンドラーメソッド

@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {

    @CrossOrigin("http://example.com")
    @RequestMapping(method = RequestMethod.GET, "/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

Springは、両方のアノテーションの属性を組み合わせて、マージされたCORS構成を作成します。

ここで、両方のメソッドの maxAge は3,600秒で、メソッド remove()はすべてのオリジンを許可し、メソッド retrieve()はオリジンのみを許可しますhttp://example.comから。

3. グローバルCORS構成

As an alternative to the fine-grained annotation-based configuration, Spring lets us define a global CORS configuration out of our controllers. This is similar to using a Filter-based solution but can be declared within Spring MVC and combined with a fine-grained @CrossOrigin configuration.

By default, all origins and GET, HEAD, and POST methods are allowed.

3.1. JavaConfig

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
}

上記の例では、アプリケーション内の任意のオリジンから任意のエンドポイントへのCORSリクエストを有効にします。

これをもう少しロックダウンするために、registerry.addMappingメソッドはCorsRegistrationオブジェクトを返します。これは、追加の構成に使用できます。 許可されたオリジンの配列を指定できるallowedOriginsメソッドもあります。 これは、実行時に外部ソースからこの配列をロードする必要がある場合に役立ちます。

さらに、設定に使用できる allowedMethods allowedHeaders exposedHeaders maxAge allowCredentialsもあります。応答ヘッダーとカスタマイズオプション。

3.2. XML名前空間

この最小限のXML構成により、JavaConfigと同じデフォルトプロパティを使用して /**パスパターンでCORSが有効になります。

<mvc:cors>
    <mvc:mapping path="/**" />
</mvc:cors>

カスタマイズされたプロパティを使用して、いくつかのCORSマッピングを宣言することもできます。

<mvc:cors>

    <mvc:mapping path="/api/**"
        allowed-origins="http://domain1.com, http://domain2.com"
        allowed-methods="GET, PUT"
        allowed-headers="header1, header2, header3"
        exposed-headers="header1, header2" allow-credentials="false"
        max-age="123" />

    <mvc:mapping path="/resources/**"
        allowed-origins="http://domain1.com" />

</mvc:cors>

4. SpringSecurityを使用したCORS

プロジェクトでSpringSecurityを使用する場合は、CORSで適切に機能するように追加の手順を実行する必要があります。 これは、CORSを最初に処理する必要があるためです。 それ以外の場合、SpringSecurityはSpringMVCに到達する前にリクエストを拒否します。

幸い、SpringSecurityはすぐに使用できるソリューションを提供します。

@EnableWebSecurity
public class WebSecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.cors().and()...
    }
}

この記事で詳しく説明しています。

5. 使い方

CORSリクエストは、登録されているさまざまなHandlerMappingsに自動的にディスパッチされます。 CORSプリフライトリクエストを処理し、 CorsProcessor 実装(デフォルトでは DefaultCorsProcessor )を使用してCORSの単純なリクエストと実際のリクエストをインターセプトし、関連するCORSレスポンスヘッダー( Access-Control-など)を追加します。 Allow-Origin )。

CorsConfiguration allows us to specify how the CORS requests should be processed, including allowed origins, headers, and methods, among others. さまざまな方法で提供できます。

  • AbstractHandlerMapping#setCorsConfiguration()を使用すると、 / api /**などのパスパターンにマップされた複数のCorsConfigurationを含むMapを指定できます。 。
  • サブクラスは、 AbstractHandlerMapping#getCorsConfiguration(Object、HttpServletRequest)メソッドをオーバーライドすることにより、独自のCorsConfigurationを提供できます。
  • ハンドラーは、 CorsConfigurationSource インターフェースを実装して( ResourceHttpRequestHandler が現在行っているように)、各要求にCorsConfigurationを提供できます。

6. 結論

この記事では、SpringがアプリケーションでCORSを有効にするためのサポートをどのように提供するかを示しました。

コントローラの設定から始めました。 CORSを1つの特定のメソッドまたはコントローラー全体に対して有効にするには、アノテーション@CrossOriginを追加するだけでよいことがわかりました。

また、コントローラーの外部でCORS構成を制御するために、JavaConfigまたはXMLのいずれかを使用して構成ファイルでこれをスムーズに実行できることも学びました。

例の完全なソースコードは、GitHubから入手できます。