親バカエンジニアのナレッジ帳

webのエンジニアをやっており、日頃の開発で詰まったことや書き残しておきたいことを載せています。

Spring Boot のCORS対策

CORSとは?

通常Webページでは、同一生成元ポリシー(Same Origin Policy)によってWebページを生成したドメイン以外へのHTTPリクエストができません。
しかし、外部リソースから情報を取得してページ内で表示したいというニーズは当然のようにあり、CORSという仕組みができました。
CORSはCross-Origin Resource Sharingの略で、いわゆるオリジン間リソース共有であり、異なるドメイン間でも情報のやり取りが可能になります。

ざっくり説明すればXMLHttpRequestをリクエストヘッダーに追加し、異なるリソースにアクセスすることをブラウザに指示するのです。
余談ですが、cookieの情報を送りたい場合はCredentialも付与する必要があるなど、アクセスの仕方によって必要となるヘッダーは異なります。

CORSの対策

さて、一見便利に見えるCORSですが、悪用されることも容易に想像できますね。
もしどのドメインからでもアクセスできるようになってしまえば、
・GETで取得した情報を勝手に使われる。
・アクセスの仕方によって個人情報を取得される恐れがある。

などなど考えられることは様々であり、許可するアクセス元は予めしっかり制御しておかなければいけないのです。
※元々誰でも使用できるAPIを作りたいだけなのであればもちろん制御は不要です。

APIを使用するサービスであればCORSの対策は基本中の基本です。
あらゆるフレームワークで容易に対策できるようになっていることでしょう。

Spring Bootでの対策

今までの説明を受けて、Spring Bootではどうなっているのか見ていきましょう。

方法1 @CrossOriginアノテーション

1つ目の方法として、@RequestMappingがついているメソッドやクラスに@CrossOriginアノテーションをつける方法があります。
特定のAPIに限っては無制限にアクセスさせるような場合に便利ですね。

方法2 Spring SecurityでCORSの設定をする方法

ログインの認証やCSRFの設定を容易にできるSpring Securityですが、CORSの設定も簡単にできます。
方法1に比べて、こちらの方法の方が柔軟に設定できます。

まずはSpring Securityのインストール

Mavenでやる場合、またはgradleでやる場合はそれぞれ以下でインストールします。

Maven - application.ymlに以下記載

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
</dependency>

gradle - build.gradleに以下記載

dependencies {
    compile('org.springframework.boot:spring-boot-starter-security')
}
WebSecurityConfigurerAdapterにCORSの設定

以下のようなWebSecurityConfigurerAdapterを継承したConfigファイル(確かデフォルトであったかな?)にCORSの設定を入れればOKです。
やはり著名なフレームワークでは容易に設定できるようになっていますね。

@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Bean
	public CorsConfigurationSource corsFilter() {
		CorsConfiguration configuration = new CorsConfiguration();
		configuration.setAllowCredentials(true);        // CORSリクエストでcookie情報の取得を許可するか
		configuration.setAllowedOrigins('ドメイン名');   // CORSリクエストを許可するドメイン
		configuration.setAllowedHeaders(Arrays.asList(  // CORSリクエストで受信を許可するヘッダー情報(以下は例です)
				"Access-Control-Allow-Headers",
				"Access-Control-Allow-Origin",
				"Access-Control-Request-Method",
				"Access-Control-Request-Headers",
				"Cache-Control",
				"Content-Type",
				"Accept-Language"));
		configuration.setAllowedMethods(Arrays.asList("GET", "POST"));  // CORSリクエストを許可するHTTPメソッド

		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		source.registerCorsConfiguration("/cors", configuration); // CORSリクエストを許可するURLの形式(特に決まりがなければ「/**」でもOK)

		return source;
	}
}