Spring Securityを使用したRESTサービスの基本認証およびダイジェスト認証
目次
1. 概要
この記事では、set up both Basic and Digest Authentication on the same URI structure of a REST APIを実行する方法について説明します。 前回の記事では、RESTサービスを保護する別の方法であるform-based authenticationについて説明しました。そのため、基本認証とダイジェスト認証が自然な代替手段であり、よりRESTfulな方法でもあります。
2. 基本認証の構成
フォームベース認証がRESTfulサービスに理想的でない主な理由は、Spring Securityがmake use of Sessionsを実行することです。これはもちろんサーバー上の状態であるため、the statelessness constraints in RESTは実質的に無視されます。
基本認証を設定することから始めます。最初に、古いカスタムエントリポイントを削除し、メインの<http>セキュリティ要素からフィルタリングします。
BasicAuthenticationFilterとBasicAuthenticationEntryPointの両方の作成と配線を処理する単一の構成行(<http-basic />)で、基本認証のサポートがどのように追加されたかに注意してください。
2.1. ステートレス制約を満たす–セッションを取り除く
RESTfulアーキテクチャスタイルの主な制約の1つは、original dissertationが読み取るように、クライアント/サーバー通信が完全にstatelessであることです。
5.1.3 Stateless
次に、クライアントとサーバーの対話に制約を追加します。通信は、セクション3.4.3(図5-3)のクライアントステートレスサーバー(CSS)スタイルのように、本質的にステートレスである必要があります。サーバーには、リクエストを理解するために必要なすべての情報が含まれている必要があり、サーバーに保存されているコンテキストを利用することはできません。 Session state is therefore kept entirely on the client。
サーバー上のSessionの概念は、Spring Securityで長い歴史を持つものであり、これまで、特に名前空間を使用して構成を行った場合、完全に削除することは困難でした。
ただし、Spring Securityaugmentsは、セッション作成用のnew stateless optionを使用した名前空間構成です。これにより、Springによってセッションが作成または使用されないことが効果的に保証されます。 この新しいオプションでは、セッションに関連するすべてのフィルターがセキュリティフィルターチェーンから完全に削除され、各要求に対して認証が実行されます。
3. ダイジェスト認証の構成
前の構成から始めて、ダイジェスト認証の設定に必要なフィルターとエントリポイントはBeanとして定義されます。 次に、digest entry pointは、舞台裏で<http-basic>によって作成されたものをオーバーライドします。 最後に、カスタムdigest filterは、セキュリティ名前空間のafterセマンティクスを使用してセキュリティフィルターチェーンに導入され、基本認証フィルターの直後に配置されます。
残念ながら、セキュリティ名前空間には、基本認証を<http-basic>で構成する方法で、ダイジェスト認証を自動的に構成するsupportはありません。 そのため、必要なBeanを手動で定義し、セキュリティ構成に手動で配線する必要がありました。
4. 同じRESTfulサービスで両方の認証プロトコルをサポートする
Spring Securityでは、基本認証またはダイジェスト認証のみを簡単に実装できます。サービスの構成とテストに新しいレベルの複雑さをもたらす同じURIマッピングで、同じRESTful Webサービスに対して両方をサポートしています。
4.1. 匿名のリクエスト
セキュリティチェーンに基本フィルターとダイジェストフィルターの両方がある場合、anonymous request –認証資格情報(Authorization HTTPヘッダー)を含まない要求–がSpring Securityによって処理される方法は– 2つの認証フィルターが%を検出します(t2)sであり、フィルターチェーンの実行を継続します。 次に、リクエストがどのように認証されなかったかを確認すると、AccessDeniedExceptionがスローされ、ExceptionTranslationFilterにキャッチされます。これにより、ダイジェストエントリポイントが開始され、クライアントに資格情報の入力が求められます。
基本フィルターとダイジェストフィルターの両方の責任は非常に狭く、要求内の認証資格情報の種類を識別できない場合、セキュリティフィルターチェーンを実行し続けます。 このため、Spring Securityは、同じURIで複数の認証プロトコルをサポートするように柔軟に構成できます。
正しい認証資格情報(基本認証またはダイジェスト認証)を含む要求が作成されると、そのプロトコルが正しく使用されます。 ただし、匿名要求の場合、クライアントはダイジェスト認証資格情報の入力のみを求められます。 これは、ダイジェストエントリポイントがSpringSecurityチェーンのメインの単一エントリポイントとして構成されているためです。そのようなdigest authentication can be considered the default。
4.2. 認証資格情報を使用したリクエスト
基本認証のrequest with credentialsは、プレフィックス“Basic”で始まるAuthorizationヘッダーによって識別されます。 そのような要求を処理するとき、資格情報は基本認証フィルターでデコードされ、要求は許可されます。 同様に、ダイジェスト認証の認証情報を使用するリクエストでは、Authorizationヘッダーにプレフィックス“Digest”が使用されます。
5. 両方のシナリオのテスト
テストは、基本またはダイジェストのいずれかで認証した後に新しいリソースを作成することにより、RESTサービスを使用します。
@Test
public void givenAuthenticatedByBasicAuth_whenAResourceIsCreated_then201IsReceived(){
// Given
// When
Response response = given()
.auth().preemptive().basic( ADMIN_USERNAME, ADMIN_PASSWORD )
.contentType( HttpConstants.MIME_JSON ).body( new Foo( randomAlphabetic( 6 ) ) )
.post( paths.getFooURL() );
// Then
assertThat( response.getStatusCode(), is( 201 ) );
}
@Test
public void givenAuthenticatedByDigestAuth_whenAResourceIsCreated_then201IsReceived(){
// Given
// When
Response response = given()
.auth().digest( ADMIN_USERNAME, ADMIN_PASSWORD )
.contentType( HttpConstants.MIME_JSON ).body( new Foo( randomAlphabetic( 6 ) ) )
.post( paths.getFooURL() );
// Then
assertThat( response.getStatusCode(), is( 201 ) );
}
基本認証を使用したテストでは、サーバーが認証を要求したかどうかに関係なく、要求preemptivelyに資格情報が追加されることに注意してください。 これは、サーバーがクライアントに資格情報を要求する必要がないようにするためです。要求があった場合、それがデフォルトであるため、ダイジェスト資格情報が要求されるためです。
6. 結論
この記事では、RESTfulサービスの基本認証とダイジェスト認証の両方の構成と実装について説明し、主にSpring Security名前空間のサポートとフレームワークのいくつかの新機能を使用しました。