Spring Security - @PreFilterと@PostFilter

Spring Security – @PreFilterおよび@PostFilter

1. 概要

この記事では、@PreFilterおよび@PostFilterアノテーションを使用してSpringアプリケーションの操作を保護する方法を学習します。

認証されたプリンシパル情報と一緒に使用すると、@PreFilterおよび@PostFilterを使用して、Spring式言語を使用してきめ細かいセキュリティルールを定義できます。

2. @PreFilter@PostFilterの紹介

簡単に言えば、@PreFilterおよび@PostFilterアノテーションは、定義したカスタムセキュリティルールに基づくused to filter lists of objectsです。

@PostFilterはメソッドのリターンリストをapplying that rule to every element in the listでフィルタリングする規則を定義する。 評価された値がtrueの場合、アイテムはリストに保持されます。 それ以外の場合、アイテムは削除されます。

@PreFilterは非常によく似た方法で機能しますが、フィルタリングは、注釈付きメソッドへの入力パラメーターとして渡されるリストに適用されます。

両方の注釈は、メソッドまたはタイプ(クラスおよびインターフェース)で使用できます。 この記事全体を通して、メソッドでのみ使用します。

これらの注釈はデフォルトではアクティブではありません。セキュリティ構成で@EnableGlobalMethodSecurity注釈とprePostEnabled = trueを使用して有効にする必要があります。

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    // ...
}

3. セキュリティルールの作成

これらの2つのアノテーションにセキュリティルールを記述するために、Spring-EL式を利用します。組み込みオブジェクトfilterObjectを使用して、テスト対象の特定のリスト要素への参照を取得することもできます。

Spring Securityは、非常に具体的で正確なルールを作成するためのmany other built-in objectsを提供します。

For exampleの場合、@PreFilterを使用して、Taskオブジェクトのassigneeプロパティが現在認証されているユーザーのnameと等しいかどうかを確認できます。

@PostFilter("filterObject.assignee == authentication.name")
List findAll() {
    ...
}

メソッドで最初にすべてのタスクを実行して取得し、リストのすべてのタスクをフィルタールールに渡すため、ここでは@PostFilterアノテーションを使用しました。

したがって、認証されたユーザーがmichaelの場合、データベースに割り当てられたタスクがある場合でも、findAllメソッドによって返されるタスクの最終リストにはmichaelに割り当てられたタスクのみが含まれます。 jimおよびpam

それでは、ルールをもう少し面白くしましょう。 ユーザーがマネージャーである場合、誰に割り当てられているかに関係なく、すべてのタスクを表示できると仮定します。

@PostFilter("hasRole('MANAGER') or filterObject.assignee == authentication.name")
List findAll() {
    // ...
}

組み込みメソッドhasRoleを使用して、認証されたユーザーがMANAGERの役割を持っているかどうかを確認しました。 hasRoleがtrueを返す場合、タスクは最終リストに保持されます。 したがって、ユーザーがマネージャーである場合、ルールはリスト内のすべてのアイテムに対してtrueを返します。 したがって、最終リストにはすべてのアイテムが含まれます。

次に、@PreFilterを使用して、パラメーターとしてsaveメソッドに渡されるリストをフィルター処理しましょう。

@PreFilter("hasRole('MANAGER') or filterObject.assignee == authentication.name")
Iterable save(Iterable entities) {
    // ...
}

セキュリティルールは、@PostFilterの例で使用したものと同じです。 ここでの主な違いは、メソッドが実行される前にリストアイテムがフィルタリングされるため、リストから一部のアイテムを削除できるため、データベースに保存されないことです。

したがって、マネージャーではないjimは、タスクのリストを保存しようとする可能性があり、その一部はpamに割り当てられています。 ただし、jimに割り当てられたタスクのみが含まれ、他のタスクは無視されます。

4. 大規模なリストでのパフォーマンス

@PreFilterは本当にクールで使いやすいですが、フェッチ操作によってすべてのデータが取得され、後でフィルターが適用されるため、非常に大きなリストを処理する場合は非効率になる可能性があります。

たとえば、データベースに数千のタスクがあり、現在pamに割り当てられている5つのタスクを取得するとします。 @PreFilter,を使用する場合、データベース操作は最初にすべてのタスクをフェッチし、それらすべてを反復処理して、pamに割り当てられていないタスクを除外します。

5. 結論

この簡単な記事では、Spring Securityの@PreFilterおよび@PostFilterアノテーションを使用して、シンプルでありながら安全なアプリケーションを作成する方法について説明しました。

完全なコード例in this Github repositoryを確認してください。