1. 概要

Spring Securityは、SpringDataとの統合を適切にサポートします。 前者はアプリケーションのセキュリティ面を処理しますが、後者はアプリケーションのデータを含むデータベースへの便利なアクセスを提供します。

この記事では、 SpringセキュリティをSpringデータと統合して、よりユーザー固有のクエリを有効にする方法について説明します。

2. Spring Security+Springデータ構成

Spring Data JPA の紹介では、SpringプロジェクトでSpringDataをセットアップする方法を説明しました。 春のセキュリティと春のデータを有効にするために、通常どおり、JavaまたはXMLベースの構成を採用できます。

2.1. Java構成

からそれを思い出してください SpringSecurityログインフォーム (セクション4と5)、アノテーションベースの構成を使用して、SpringSecurityをプロジェクトに追加できます。

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    // Bean definitions
}

その他の構成の詳細には、必要に応じて、フィルター、Bean、およびその他のセキュリティルールの定義が含まれます。

SpringSecurityでSpringDataを有効にするには、このBeanをWebSecurityConfigに追加するだけです。

@Bean
public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
    return new SecurityEvaluationContextExtension();
}

上記の定義により、クラスに注釈が付けられたスプリングデータ固有の式の自動解決をアクティブ化できます。

2.2. XML構成

XMLベースの構成は、SpringSecurity名前空間を含めることから始まります。

<beans:beans xmlns="http://www.springframework.org/schema/security"
  xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
  http://www.springframework.org/schema/security
  http://www.springframework.org/schema/security/spring-security.xsd">
...
</beans:beans>

Javaベースの構成と同様に、XMLまたは名前空間ベースの構成では、 SecurityEvaluationContextExtensionbeanをXML構成ファイルに追加します。

<bean class="org.springframework.security.data.repository
  .query.SecurityEvaluationContextExtension"/>

SecurityEvaluationContextExtension を定義すると、SpringDataクエリ内からSpringSecurityのすべての一般的な式を使用できるようになります。

このような一般的な表現には、 priority、authentication、isAnonymous()、hasRole([role])、isAuthenticated、などがあります。

3. 使用例

SpringデータとSpringセキュリティのいくつかのユースケースを考えてみましょう。

3.1. AppUserフィールドの更新を制限する

この例では、 App UserlastLoginフィールドの更新を現在認証されている唯一のユーザーに制限する方法を見ていきます。

つまり、 updateLastLogin メソッドがトリガーされると、現在認証されているユーザーのlastLoginフィールドのみが更新されます。

これを実現するために、以下のクエリをUserRepositoryインターフェイスに追加します。

@Query("UPDATE AppUser u SET u.lastLogin=:lastLogin WHERE" 
  +" u.username = ?#{ principal?.username }")
void updateLastLogin (Date lastLogin);

SpringデータとSpringセキュリティの統合がなければ、通常、ユーザー名を引数としてupdateLastLoginに渡す必要があります。

間違ったユーザー資格情報が提供された場合、ログインプロセスは失敗し、アクセスの検証を確認する必要はありません。

3.2. ページ付けを使用して特定のAppUser’コンテンツをフェッチする

SpringDataとSpringSecurityが完全に連携して機能する別のシナリオは、現在認証されているユーザーが所有するデータベースからコンテンツを取得する必要がある場合です。

たとえば、ツイーターアプリケーションがある場合、現在のユーザーが作成または高く評価したツイートを、パーソナライズされたフィードページに表示したい場合があります。

もちろん、これには、データベース内の1つ以上のテーブルと対話するためのクエリの記述が含まれる場合があります。 SpringDataとSpringSecurityを使用すると、これは次のように書くのと同じくらい簡単です。

public interface TweetRepository extends PagingAndSortingRepository<Tweet, Long> {
    @Query("SELECT twt FROM Tweet twt JOIN twt.likes AS lk WHERE lk = ?#{ principal?.username }" +
      " OR twt.owner = ?#{ principal?.username }")
    Page<Tweet> getMyTweetsAndTheOnesILiked(Pageable pageable);
}

結果をページ分割する必要があるため、TweetRepositoryは上記のインターフェイス定義のPagingAndSortingRepositoryを拡張します。

4. 結論

SpringDataとSpringSecurityの統合により、Springアプリケーションの認証済み状態の管理に多くの柔軟性がもたらされます。

このセッションでは、SpringセキュリティをSpringデータに追加する方法について説明しました。 SpringDataまたはSpringSecurityの他の強力な機能の詳細については、 SpringDataおよびSpringSecurityの記事のコレクションを参照してください。

いつものように、コードスニペットはGitHubにあります。