1. 概要

Spring Securityは、認証クレデンシャルの受信と解析を処理します。

この短いチュートリアルでは、ハンドラーコード内で、リクエストからSecurityContext情報を取得する方法を見ていきます。

2. @CurrentSecurityContextアノテーション

ボイラープレートコードを使用して、セキュリティコンテキストを読み取ることができます。

SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();

ただし、現在、に役立つ@CurrentSecurityContextアノテーションがあります。

さらに、アノテーションを使用すると、コードがより宣言的になり、authenticationオブジェクトが注入可能になります。 @CurrentSecurityContext を使用すると、現在のユーザーのPrincipal実装にアクセスすることもできます。

以下の例では、認証プリンシパルの名前など、セキュリティコンテキストデータを取得するいくつかの方法を見ていきます。 また、コードをテストする方法についても説明します。

3. Mavenの依存関係

Spring Bootの最新バージョンがある場合は、 spring-boot-starter-security:の依存関係を含めるだけで済みます。

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

それ以外の場合は、spring-security-coreを最小バージョンの5.2.1.RELEASEにアップグレードできます。

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
    <version>5.2.1.RELEASE</version>
</dependency>

4. @CurrentSecurityContextを使用した実装

SpEL(Spring Expression Language)と @CurrentSecurityContext を使用して、認証オブジェクトまたはプリンシパル注入できます。 SpELはタイプルックアップと連携して機能します。 タイプチェックはデフォルトでは適用されませんが、@CurrentSecurityContextアノテーションのerrorOnInvalidTypeパラメーターを介して有効にできます。

4.1. 認証オブジェクトの取得

Authentication オブジェクトを読んで、その詳細を返すことができるようにしましょう。

@GetMapping("/authentication")
public Object getAuthentication(@CurrentSecurityContext(expression = "authentication") 
  Authentication authentication) {
    return authentication.getDetails();
}

SpEL式は、認証オブジェクト自体を参照していることに注意してください。

それをテストしてみましょう:

@Test
public void givenOAuth2Context_whenAccessingAuthentication_ThenRespondTokenDetails() {
    ClientCredentialsResourceDetails resourceDetails = 
      getClientCredentialsResourceDetails("baeldung", singletonList("read"));
    OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails);

    String authentication = executeGetRequest(restTemplate, "/authentication");

    Pattern pattern = Pattern.compile("\\{\"remoteAddress\":\".*"
      + "\",\"sessionId\":null,\"tokenValue\":\".*"
      + "\",\"tokenType\":\"Bearer\",\"decodedDetails\":null}");
    assertTrue("authentication", pattern.matcher(authentication).matches());
}

この例では、接続のすべての詳細を取得していることに注意してください。 テストコードではremoteAddressまたはtokenValueを予測できないため、正規表現を使用して結果のJSONを確認しています。

4.2. プリンシパルの取得

認証データからPrincipalのみが必要な場合は、SpEL式と挿入されたオブジェクトを変更できます。

@GetMapping("/principal")
public String getPrincipal(@CurrentSecurityContext(expression = "authentication.principal") 
  Principal principal) { 
    return principal.getName(); 
}

この場合、 getName メソッドを使用して、Principal名のみを返します。

それをテストしてみましょう:

@Test
public void givenOAuth2Context_whenAccessingPrincipal_ThenRespondBaeldung() {
    ClientCredentialsResourceDetails resourceDetails = 
       getClientCredentialsResourceDetails("baeldung", singletonList("read"));
    OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails);

    String principal = executeGetRequest(restTemplate, "/principal");

    assertEquals("baeldung", principal);
}

ここでは、クライアントの資格情報に追加された名前 baeldung が検出され、ハンドラーに挿入されたプリンシパルオブジェクト内から返されます。

5. 結論

この記事では、現在のセキュリティコンテキスト内のプロパティにアクセスし、ハンドラーメソッドのパラメーターにそれらを挿入する方法を見てきました。

これは、SpELと@CurrentSecurityContextアノテーションを利用して行いました。

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