1. 概要

Keycloak は、最新のアプリケーション(SPA、モバイルアプリ、APIなど)を保護するオープンソースのIDおよびアクセス管理サーバーです。 Keycloakは、Security Assertion Markup Language(SAML)2.0、Single Sign-On(SSO)、OpenID Connect(OIDC)などの業界標準プロトコルをサポートしています。

さらに、このチュートリアルでは、Keycloakを利用して、 OIDC (OpenID Connect)を使用してSOAPWebサービスを認証および承認する方法を学習します。

2. SOAPWebサービスを開発する

簡単に説明すると、Spring Bootを使用してSOAPWebサービスを構築する方法を学びましょう。

2.1. Webサービスの操作

すぐに、操作を定義しましょう:

  • getProductDetails :指定された製品IDの製品詳細を返します。 また、userロールを持つユーザーがこの操作を要求できると仮定します。
  • deleteProduct :指定された製品IDの製品を削除します。 また、adminを持つユーザーのみがこの操作を要求できます。

2つの操作とRBAC(ロールベースのアクセス制御)を定義しました。

2.2. XSDを定義する

とりわけ、product.xsdを定義しましょう。

<xs:element name="getProductDetailsRequest">
    ...
</xs:element>
<xs:element name="deleteProductRequest">
    ...
</xs:element>
    ...
</xs:schema>

また、wsdl4jおよびSpring BootWebサービスの依存関係を追加しましょう。

<dependency>
    <groupId>wsdl4j</groupId>
    <artifactId>wsdl4j</artifactId>
    <version>1.6.3</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web-services</artifactId>
    <version>2.5.4</version>
</dependency>

2.3. ウェブサービス

さらに、SOAPWebサービスを開発しましょう。

@PayloadRoot(namespace = "http://www.baeldung.com/springbootsoap/keycloak", localPart = "getProductDetailsRequest")
@ResponsePayload
public GetProductDetailsResponse getProductDetails(@RequestPayload GetProductDetailsRequest request) {
    ...
}
@PayloadRoot(namespace = "http://www.baeldung.com/springbootsoap/keycloak", localPart = "deleteProductRequest")
@ResponsePayload
public DeleteProductResponse deleteProduct(@RequestPayload DeleteProductRequest request) {
    ...
}

このWebサービスは、 cURL Postman SOAPUIなどのいくつかのツールを使用してテストできます。 今後は、SOAPWebサービスを保護する方法を見ていきましょう。

3. Keycloakの設定

まず、OpenIdConnectを使用してWebサービスを保護するためにKeycloakを構成しましょう。

3.1. クライアントを作成する

通常、クライアントはKeycloaksの認証サービスを必要とするアプリケーションです。 また、クライアントを作成するときに、次を選択します。

  • ルートURLとしてのアプリケーションURL
  • openid-connectクライアントプロトコルとして
  • 機密asアクセスタイプ
  • 認証が有効およびサービスアカウントが有効をオンにします

さらに、サービスアカウントを有効にすると、アプリケーション(クライアント)がKeycloakで認証できるようになります。 続いて、 Client CredentialsGrantタイプのフローを認証フローに提供します。

 

最後に、保存をクリックし、クレデンシャルタブをクリックして、シークレットをメモします。したがって、Spring Bootの一部として必要になります。 ] 構成。

3.2. ユーザーと役割

次に、2人のユーザーを作成し、それらに役割とパスワードを割り当てましょう。

 

まず、ロール adminuserを作成しましょう。Keycloakを使用すると、レルムロールクライアントロールの2種類のロールを作成できます。 。 ただし、最初にクライアントロールを作成しましょう。

クライアントをクリックし、クライアントを選択して、役割タブをクリックします。 次に、 adminuser:の2つのロールを作成します

 

KeycloakはLDAPまたはAD(Active Directory)からユーザーを取得できますが、簡単にするために、ユーザーを手動で構成して役割を割り当てましょう。

2人のユーザーを作成しましょう。 まず、ユーザー、ユーザーの追加の順にクリックします。

 

それでは、ユーザーに役割を割り当てましょう。

もう一度、ユーザーをクリックしてユーザーを選択し、編集をクリックして次にロールマッピングタブをクリックし、クライアントロールからクライアントを選択します]そして使用可能な役割で役割を選択します。管理者の役割を1人のユーザーに割り当て、ユーザーの役割を別の用途に割り当てましょう。

 

4. スプリングブート構成

同様に、SOAPWebサービスを保護しましょう。

4.1. Keycloak –SpringBootの統合

まず、Keycloakの依存関係を追加しましょう。

Keycloakは、Spring Bootの自動構成を利用し、統合を容易にするアダプターを提供します。 それでは、依存関係を更新して、このKeycloakアダプターを含めましょう。

<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-spring-boot-starter</artifactId>
    <version>15.0.2</version>			
</dependency>

次に、Keycloak構成をapplication.propertiesに追加しましょう。

keycloak.enabled=true
keycloak.realm=baeldung-soap-services
keycloak.auth-server-url=http://localhost:8080/auth
keycloak.bearer-only=true
keycloak.credentials.secret=14da6f9e-261f-489a-9bf0-1441e4a9ddc4
keycloak.ssl-required=external
keycloak.resource=baeldung-soap-services
keycloak.use-resource-role-mappings=true

Keycloakドキュメントから:

  • keycloak.enabled :構成によってKeycloakSpringBootアダプターを有効にできるようにします。 デフォルト値はtrueです。
  • keycloak.realm :Keycloakレルム名であり、必須です
  • keycloak.auth-server-url :ベースURLは必須であり、Keycloakサーバーのものです。 通常、これは http(s):// host:port /authの形式です。
  • keycloak.bearer-only :デフォルト値は falseですが、アダプターがトークンを検証するには、trueに設定します。
  • keycloak.credentials。 秘密 :Keycloakで設定されている必須のclient-secret
  • keycloak.ssl-required :デフォルト値はexternalです。 つまり、すべての外部リクエスト( localhost を除く)はhttpsプロトコル上にある必要があります。
  • keycloak.resource :アプリケーションの必須のクライアントID
  • keycloak.use-resource-role-mappings:デフォルトは false ですが、アダプターがアプリケーションレベルのトークン内を検索するようにtrueに設定しますユーザーのロールマッピング。

4.2. グローバルメソッドセキュリティを有効にする

以前の構成に加えて、Webサービスを保護するためにセキュリティ制約を指定する必要があります。 これらの制約により、不正アクセスを制限できます。 たとえば、useradminアクションから制限する必要があります。

制約を設定するには、次の2つの方法があります。

  1. アプリケーション構成ファイルでsecurity-constraintsおよびsecurity-collectionsを宣言します。
  2. @EnableGlobalMethodSecurityを使用したメソッドレベルのセキュリティ。

SOAP Webサービスの場合、セキュリティ制約は、きめ細かい制御を提供するには不十分です。 さらに、これらの制約を宣言することは冗長です。

今後は、 @EnableGlobalMethodSecurity の機能を活用して、SOAPWebサービスの操作を保護しましょう。

4.3. KeycloakWebSecurityConfigurerAdapterの定義

KeycloakWebSecurityConfigurerAdapterは、WebSecurityConfigurerAdapterを拡張し、セキュリティコンテキスト構成を簡素化するオプションの便利なクラスです。 さらに、このアダプターを拡張し、@EnableGlobalMethodSecurityを使用するクラスKeycloakSecurityConfigを定義しましょう。

この階層を表すクラス図:

それでは、KeycloakSecurityConfigクラスを構成しましょう。

@KeycloakConfiguration
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http
          .csrf()
          .disable()
          .authorizeRequests()
          .anyRequest()
          .permitAll();
    }
}

@KeycloakConfigurationは、KeycloakとSpring Bootの統合に必要なすべてのアノテーションを定義します。

4.4. 承認の追加

最後に、 @RolesAllowed アノテーション( JSR-250 の一部)を使用して、SOAPWebサービス操作を承認しましょう。

それでは、アクセスロールを使用してメソッドを構成しましょう。 これを行うには、@RolesAllowedアノテーションを使用しましょう 。 Keycloakでuseradmin、の2つの異なる役割を定義したことを思い出してください。 各Webサービスを次の役割で定義しましょう。

@RolesAllowed("user")
@PayloadRoot(namespace = "http://www.baeldung.com/springbootsoap/keycloak", localPart = "getProductDetailsRequest")
@ResponsePayload
public GetProductDetailsResponse getProductDetails(@RequestPayload GetProductDetailsRequest request) {
    ...
}
@RolesAllowed("admin")
@PayloadRoot(namespace = "http://www.baeldung.com/springbootsoap/keycloak", localPart = "deleteProductRequest")
@ResponsePayload
public DeleteProductResponse deleteProduct(@RequestPayload DeleteProductRequest request) {
    ...
}

これで設定は完了です。

5. アプリケーションをテストする

5.1. セットアップを確認してください

アプリケーションの準備ができたので、curlを使用してSOAPWebサービスのテストを開始しましょう。

curl -d @request.xml -i -o -X POST --header 'Content-Type: text/xml' http://localhost:18080/ws/api/v1

最終的に、すべての構成が正しい場合、アクセス拒否の応答が返されます。

<SOAP-ENV:Fault>
    <faultcode>SOAP-ENV:Server</faultcode>
    <faultstring xml:lang="en">Access is denied</faultstring>
</SOAP-ENV:Fault>

予想どおり、リクエストにアクセストークンが含まれていないため、Keycloakはリクエストを拒否します。

5.2. アクセストークンの取得

この時点で、Keycloakからアクセストークンを取得して、SOAPWebサービスにアクセスしましょう。 通常、フローには次のものが含まれます。

 

  • まず、ユーザーが自分の資格情報をアプリケーションに送信します
  • アプリケーションは、client-idclient-secretをこれらのクレデンシャルとともにKeycloakサーバーに渡します。
  • 最後に、Keycloakは、ユーザーの資格情報と役割に基づいて、アクセストークン、更新トークン、およびその他のメタデータを返します。

Keycloakは、クライアントがアクセストークンを要求するためのトークンエンドポイントを公開します。  通常、このエンドポイントは次の形式です。

:// / auth / realms / / protocol / openid-connect / token

例えば:

http:// localhost:8080 / auth / realms / baeldung / protocol / openid-connect / token

それでは、アクセストークンを取得しましょう。

curl -L -X POST 'http://localhost:8080/auth/realms/baeldung-soap-services/protocol/openid-connect/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'client_id=baeldung-soap-services' \
--data-urlencode 'client_secret=14da6f9e-261f-489a-9bf0-1441e4a9ddc4' \
--data-urlencode 'username=janedoe' \
--data-urlencode 'password=password'

実際には、メタデータとともにアクセストークンと更新トークンを取得します。

{
    "access_token": "eyJh ...",
    "expires_in": 300,
    "refresh_expires_in": 1800,
    "refresh_token": "eyJh ...",
    "token_type": "Bearer",
    "not-before-policy": 0,
    "session_state": "364b8f3e-34ff-4ca0-8895-bfbdb8b466d4",
    "scope": "profile email"
}

さらに、構成可能なexpires_inキーは、このトークンの有効期間を定義します。たとえば、上記のアクセストークンは5分(300秒)で期限切れになります。

5.3. アクセストークンを使用したWebサービスの呼び出し

この例では、前のセクションで取得したアクセストークンを使用してみましょう。 アクセストークンをBearerTokenとして使用してSOAPWebサービスを呼び出しましょう。

curl -d @request.xml -i -o -X POST -H 'Authorization: Bearer BwcYg94bGV9TLKH8i2Q' \
  -H 'Content-Type: text/xml' http://localhost:18080/ws/api/v1

正しいアクセストークンを使用すると、応答は次のようになります。

<ns2:getProductDetailsResponse xmlns:ns2="http://www.baeldung.com/springbootsoap/keycloak">
    <ns2:product>
        <ns2:id>1</ns2:id>
            ...
        </ns2:product>
</ns2:getProductDetailsResponse>

5.4. 承認

ユーザーの役割を持つユーザーjanedoeのアクセストークンを生成したことを思い出してください。 user アクセストークンを使用して、admin操作を実行してみましょう。 つまり、deleteProductを呼び出してみましょう。

curl -d @request.xml -i -o -X POST -H 'Authorization: Bearer sSgGNZ3KbMMTQ' -H 'Content-Type: text/xml' \
  http://localhost:18080/ws/api/v1

ここで、request.xmlの内容は次のとおりです。

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:key="http://www.baeldung.com/springbootsoap/keycloak">
    <soapenv:Header/>
    <soapenv:Body>
        <key:deleteProductRequest>
            <key:id>1</key:id>
        </key:deleteProductRequest>
   </soapenv:Body>
</soapenv:Envelope>

ユーザーadmin操作へのアクセスを許可されていないため、アクセスが拒否されます。

<SOAP-ENV:Fault>
    <faultcode>SOAP-ENV:Server</faultcode>
        <faultstring xml:lang="en">Access is denied</faultstring>
</SOAP-ENV:Fault>

6. 結論

このチュートリアルでは、SOAP Webサービス、keycloak構成を開発し、Keycloakを使用してWebサービスを保護する方法を示しました。 REST Webサービスを保護する方法では、疑わしいユーザーや不正アクセスからSOAPWebサービスを保護する必要があります。

いつものように、完全なソースコードはGitHubから入手できます。