原文はこちら。
The original article was written by Tim Quinn (Oracle).
https://medium.com/helidon/helidon-2-0-and-cors-14f34e2b1d17
新たにリリースされたHelidon 2.0から、簡単にCORSサポートをアプリケーションや、Health、Metrics、OpenAPIというHelidonの組み込みサービスに追加できるようになりました。
Helidon
https://helidon.io
ブラウザやその他のよくあるWebクライアントに実装されている、同一オリジンポリシー (same-origin policy) は、あるオリジン(URLスキーム、ホスト、ポート)のページやアプリが他のオリジンのリソースにアクセスすることを制限するものです。
Same Origin Policy
https://www.w3.org/Security/wiki/Same_Origin_Policy
しかし特定のケースでは、この制限を緩和することに意味がある場合があります。クロスオリジンリソース共有 (Cross-origin resource sharing, CORS) は、HTTPヘッダーを使用した標準的なアプローチで、Webクライアントとサーバーが、別のオリジンのリソースに代わって、あるオリジンからのリソースへの管理されたアクセスを許可(または拒否)するように要求するものです。
Fetch
https://www.w3.org/TR/cors/
最新のHelidon 2.0で、Helidon SEやHelidon MPのアプリケーションのエンドポイントや、Health、Metrics、OpenAPI などのHelidon組み込みサービスのエンドポイントにCORSサポートを簡単に追加できるようになりました。
About CORS in Helidon SE
https://helidon.io/docs/latest/#/se/cors/01_introduction
About CORS in Helidon MP
https://helidon.io/docs/latest/#/mp/cors/01_introduction
以下のサンプルアプリはHelidonのgreetingというサンプルアプリに触発されたものです。
Helidon SE CORS Example
https://github.com/oracle/helidon/tree/release-2.0.1/examples/cors
Helidon MP CORS Example
https://github.com/oracle/helidon/tree/release-2.0.1/examples/microprofile/cors
この例では、 http://foo.com と http://there.com のリソースからのサンプルアプリへのPUT、DELETEアクセスを許可する一方で、その他の全てのオリジンに対してはGETやHEADなどのシンプルなアクセスを許可します。
CORS in Helidon SE
pom.xmlに依存関係を追加します。
<dependency>
<groupId>io.helidon.webserver</groupId>
<artifactId>helidon-webserver-cors</artifactId>
</dependency>
コードにCorsSupportインスタンスを作成する
アプリのリソースに必要なCORSの動作を表す、CorsSupportオブジェクトを作成します。2つのCrossOriginConfigオブジェクトを使用しますが、一方はPUTとDELETEアクセス用、もう一方はその他のすべてのアクセス用です。
CorsSupport corsSupport = CorsSupport.builder()
.addCrossOriginConfig(CrossOriginConfig.builder()
.allowOrigins("http://foo.com", "http://there.com")
.allowMethods("PUT", "DELETE")
.build())
.addCrossOriginConfig(CrossOriginConfig.create())
.build();
CorsSupportインスタンスの利用
アプリケーションのパスへのルーティングを構成する、同じregisterメソッドの呼び出しでCorsSupportインスタンスを使います。
return Routing.builder()
.register(JsonSupport.create())
.register(health) // Health at "/health"
.register(metrics) // Metrics at "/metrics"
.register("/greet", corsSupport, greetService)
.build();
アプリケーションのリビルド、再起動でおしまいです。アプリで実際に CORS サポートを確認する簡単な方法を以下でご紹介します。
CORS in Helidon MP
pom.xmlに依存関係を追加します。
<dependency>
<groupId>io.helidon.microprofile</groupId>
<artifactId>helidon-microprofile-cors</artifactId>
</dependency>
@CrossOrigin
アノテーションの利用
JAX-RSリソースクラスで、HTTP OPTIONSリクエスト用のno-opメソッドを追加し、そこに注釈を付けます。
@OPTIONS
@CrossOrigin(
allowMethods = {"PUT", "DELETE"},
allowOrigins = {"http://foo.com", "http://there.com"})
public void optionsForGreeting() {}
その後、アプリをリビルド、再起動します。
Trying it out (SE and MP)
cURLを使って、アプリのエンドポイントに対するHelidonのCORSサポートを実際に試してみましょう。以下のコードスニペットでは、CORS関連のヘッダーを強調しています。
GETやHEADのような簡単なオペレーションでは、CORSは常のHTTPリクエストにヘッダーを追加するだけです。
curl -i -X GET \
-H "Origin: http://foo.com" -H "Host: here.com" \
http://localhost:8080/greet
そのレスポンスは以下のようです。
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json
Date: Thu, 30 Apr 2020 17:25:51 -0500
Vary: Origin
connection: keep-alive
content-length: 27
{"greeting":"Hello World!"}
いわゆるシンプルでない、アプリケーションのサーバー側の状態が変化する可能性のあるオペレーションの場合、CORSはpre-flightリクエストを使用して、クライアントが宣言した希望のアクセスをサーバーに「事前承認」させます。通常ブラウザはpre-flightリクエストの送信(とレスポンスのチェック)を見えないように実施しますが、以下のcURLコマンドではこのステップをシミュレートしています。
curl -i -X OPTIONS \
-H "Access-Control-Request-Method: PUT" \
-H "Origin: http://foo.com" \
-H "Host: here.com" \
http://localhost:8080/greet/greeting
リクエストされたCORSに問題がないことを示しています。
HTTP/1.1 200 OK
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Origin: http://foo.com
Date: Thu, 30 Apr 2020 17:30:59 -0500
transfer-encoding: chunked
connection: keep-alive
この時点で、クライアントは所望のPUTリクエストを発行します。この例では挨拶のことばを変更するためにPUTリクエストを発行しています。
curl -i -X PUT \
-H "Origin: http://foo.com" \
-H "Host: here.com" \
-H "Access-Control-Allow-Methods: PUT" \
-H "Access-Control-Allow-Origin: http://foo.com" \
-H "Content-Type: application/json" \
-d "{ \"greeting\" : \"Cheers\" }" \
http://localhost:8080/greet/greeting
サーバーは通常通り応答します。
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: http://foo.com
Date: Thu, 30 Apr 2020 17:32:55 -0500
Vary: Origin
connection: keep-alive
Bottom Line
わずかな追加コードで、Helidon SEやHelidon MPのアプリケーションのエンドポイントがCORSプロトコルに参加できます。そして、ここでは重要なポイントだけを紹介しますが、設定を使用して、CORS関連の変更がさらに簡単にできます。
さらに、アプリケーションにエンドポイントを追加するHelidonの組み込みサービス(health、metrics、OpenAPI)のCORSも簡単に有効化して制御できます。
完全な情報は以下のドキュメントをご覧ください。
About CORS in Helidon SE
https://helidon.io/docs/latest/#/se/cors/01_introduction
About CORS in Helidon MP
https://helidon.io/docs/latest/#/mp/cors/01_introduction