MicroProfile JWTによるスケーラブルでセキュアなマイクロサービス構築 -入門編(Part 2)-
富士通技術者ブログ~Javaミドルウェア~

2022年4月1日 初版
数村 憲治

MicroProfile Interoperable JWT RBAC(MP JWT)を使用し、Javaでセキュアなマイクロサービスを構築する方法について、Part 1に引き続き紹介します。Part 1では、マイクロサービスアーキテクチャーにおける認可システムの課題と、その解決策であるMP JWTの紹介、およびJWTの構成内容や作成についてみてきました。Part 2では、Jakarta RESTful Web Services アプリケーションにおいて、JWTの使用方法を紹介します。

なお、ここで紹介するプログラムの完全なソースコードは、以下で参照できます。

Restful Web Serviceアプリケーションの用意

使用するプログラムは以下のHelloアプリケーションです。

App.java

@ApplicationPath("/")
public class App extends Application {
}

Hello.java

@Path("hello")
@RequestScoped
public class Hello {
  @GET
  public String hello() {
    return "Hello !¥n";
  }
}

プログラムのビルドについては、https://github.com/fujitsu/app_blog/tree/master/mpjwt-202102/baseにmavenプロジェクトを用意していますので、参照ください。

上記プログラムを実行するために、MicroProfileの実装の一つである、Launcherを用意します。Launcherは、以下よりダウンロードし利用します。

https://github.com/fujitsu/launcher/releases/download/3.0/launcher-3.0.jar

Launcherの使い方は、ダウンロードしたlauncher-3.0.jarを任意の場所に置いて、javaコマンドの-jarオプションに指定するだけです(インストール作業は不要です)。詳細なLauncherの使用方法は、ドキュメントを参照してください。

$ java -jar launcher-3.0.jar --deploy hellojwt.war

Launcherはデフォルトで8080番ポートを使用しますので、このWebアプリケーションにアクセスするには、curlコマンドなどで以下のように実行します。

$ curl http://localhost:8080/hello

「Hello !」と表示されれば、正しく起動されています。

MP JWTを使用したロールの設定

続いて、このhelloアプリケーションに、特定のロールを持つ人からのみアクセスできるようにします。まず、MP JWTを使用するには、Applicationクラス(javax.ws.rs.core.Application)に対して、org.eclipse.microprofile.auth.LoginConfigを指定します。

例:App.java

@ApplicationPath("/")
@LoginConfig(authMethod = "MP-JWT")
public class App extends Application {
}

次に、「/hello」エンドポイントに対して、ロールを設定します。ロールは、javax.annotation.security.RolesAllowedのパラメーターに指定します。以下の例は、「キツネさんチーム」というロールを設定しています。

@Path("hello")
@RequestScoped
public class Hello {
  @GET
  @RolesAllowed("キツネさんチーム")
  public String hello() {
    return "Hello !¥n";
  }
}

このMP JWTを使用したアプリケーションを起動するには、JWTの署名を検証するためのパブリックキーを、Launcher起動時に指定する必要があります。パブリックキーの指定方法には、PEM形式ファイルの場所をシステムプロパティ「mp.jwt.verify.publickey.location」に指定する方法や、JWK形式をBase64エンコードして「mp.jwt.verify.publickey」に指定する方法などがあります。MP JWTでサポートするパブリックキーのフォーマットについては、Supported Public Key Formatsを、パブリックキーの指定方法については、Signature Verification Configuration Parametersを参照ください。ここでは、Base64エンコードしたJWKを指定する方法を紹介します。

MP JWTを使用したアプリケーションの起動例

$ java -Dmp.jwt.verify.publickey=eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2IiwieCI6IllBNmpBdktWcUVXOGhxUlVnb2NWOFVtNlE3cjVkaWJVTUZzZ1pQb2hYU2c9IiwieSI6IlMwRmhqMS1IOU9pdWtmSUxrWTZJM2txWGlwZm5iRnlkU1ZpSVpaamliNFU9In0= -Dmp.jwt.verify.publickey.algorithm=ES256 -jar launcher-3.0.jar --deploy hellojwt.war

このように起動したアプリケーションに対して、先ほど同様にエンドポイントにアクセスすると、以下のように、ステータスコード401(Unauthorized)が返却されます。

$ curl -I http://localhost:8080/hello
HTTP/1.1 401 Unauthorized
Server: Launcher  3.0
WWW-Authenticate: Bearer
Content-Length: 1034
Content-Language:
Content-Type: text/html

これは、「/hello」にアクセスするために必要なロールが、JWTとしてHTTPリクエストに渡されなかったためです。正しくアクセスするためには、「キツネさんチーム」というロールを含むJWT(Part 1で例示したペイロード)を、HTTPリクエストに指定する必要があります。JWTは、HTTPリクエストの「Authorization」ヘッダーに、「Bearer」の後に指定します。

$ curl http://localhost:8080/hello -H "Authorization: Bearer eyAgInR5cCI6ICJKV1QiLCAgImFsZyI6ICJFUzI1NiIsICAia2lkIjogImtleS0xMjM0In0=.eyAgImlzcyI6ICLnmbrooYzogIUiLCAgImV4cCI6IDE2NjgxMzI2NzEsICAiaWF0IjogMTYzNjU5NjY3MSwgICJ1cG4iOiAi5a-M5aOr6YCa6Iqx5a2QIiwgICJhZGRyZXNzIjogIuadseS6rOmDvea4r-WMuuadseaWsOapiyIsICAiZ3JvdXBzIjogWyLjgq3jg4Tjg43jgZXjgpPjg4Hjg7zjg6AiLCAi44Gf44Gs44GN44GV44KT44OB44O844OgIl19.de_Wqzp0aLlgp5mvIZeW-Lr8XbF1ha0PyV9kU2K80fKUvCxrxHWIMZVStKjugewVX2hQqigVpCL6u5Vp6WwsEQ=="

「Hello !」というレスポンスが得られれば、正しくロールによる認可ができたことになります。

なお、この例で使用した、パブリックキーとJWTの作成は、以下のプログラムを使用して作成しました。

Claim(JWT内に設定されている属性)値の取得

次にJWTに指定したClaim(ペイロードに指定したJSON文字列)から、値を取り出す例を紹介します。ここでは、Part 1のペイロードの例(図1を参照)から、「upn」の値を取り出します。

図1:JWTの構成
図1:JWTの構成

org.eclipse.microprofile.jwt.Claimのパラメーターに「upn」を指定し、org.eclipse.microprofile.jwt.ClaimValueとして、インジェクションします。「hello」メソッド内で実施しているように、ClaimValueのgetValueメソッドで値を取り出すことができるようになります。

public class Hello {

  @Inject
  @Claim("upn")
  private ClaimValue<String> upn;

  @GET
  @RolesAllowed("キツネさんチーム")
  public String hello() {
    return "Hello  " + upn.getValue() + " !¥n";
  }
}

このアプリケーションに対して、以下のHTTPリクエストを発行します。

$ curl http://localhost:8080/hello -H "Authorization: Bearer eyAgInR5cCI6ICJKV1QiLCAgImFsZyI6ICJFUzI1NiIsICAia2lkIjogImtleS0xMjM0In0=.eyAgImlzcyI6ICLnmbrooYzogIUiLCAgImV4cCI6IDE2NjgxMzI2NzEsICAiaWF0IjogMTYzNjU5NjY3MSwgICJ1cG4iOiAi5a-M5aOr6YCa6Iqx5a2QIiwgICJhZGRyZXNzIjogIuadseS6rOmDvea4r-WMuuadseaWsOapiyIsICAiZ3JvdXBzIjogWyLjgq3jg4Tjg43jgZXjgpPjg4Hjg7zjg6AiLCAi44Gf44Gs44GN44GV44KT44OB44O844OgIl19.de_Wqzp0aLlgp5mvIZeW-Lr8XbF1ha0PyV9kU2K80fKUvCxrxHWIMZVStKjugewVX2hQqigVpCL6u5Vp6WwsEQ=="

成功すると、「Hello 富士通花子 !」というレスポンスが得られます。

まとめ

今回のPart 2 では、Jakarta RESTful Web Services アプリケーションで、MP JWTを使用する方法を紹介しました。このように、MP JWTを使うことで、既存のJavaアプリケーションに大きな変更を加えることなく、認可のシステムを組み込むことができるようになります。

本コンテンツに関するお問い合わせ

お電話でのお問い合わせ

富士通コンタクトライン(総合窓口)

0120-933-200

受付時間:9時~12時および13時~17時30分
(土曜日・日曜日・祝日・当社指定の休業日を除く)

Webでのお問い合わせ

当社はセキュリティ保護の観点からSSL技術を使用しております。

ページの先頭へ