Spring Security - @PreFilterと@PostFilter

1概要

この記事では @PreFilter の使い方を学びます] @PostFilter 春の操作を保護する応用。

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

2 @ PreFilter @ PostFilter の紹介

簡単に言うと、 @ PreFilter アノテーションと @ PostFilter アノテーションは、定義したカスタムセキュリティルールに基づいて オブジェクトのリストをフィルタリングするために 使用されています。

@ PostFilter は、** リスト内のすべての要素にその規則を適用することによって、メソッドの戻りリストをフィルタリングするための規則を定義します。評価された値がtrueの場合、アイテムはリストに残ります。それ以外の場合、アイテムは削除されます。

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

どちらのアノテーションもメソッドや型(クラスとインタフェース)に使用できます。この記事では、これらのメソッドをメソッドにのみ使用します。

これらのアノテーションはデフォルトではアクティブになっていません - 私たちのセキュリティ設定では、 @ EnableGlobalMethodSecurity アノテーションと prePostEnabled = true でそれらを有効にする必要があります。

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

3セキュリティ規則の書き方

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

Spring Securityはhttps://docs.spring.io/spring-security/site/docs/current/reference/html/authorization.html#el-common-built-in[その他多くの組み込みオブジェクト]を提供して非常に具体的なそして正確な規則。

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

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

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

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

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

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

認証されたユーザーにMANAGERの役割があるかどうかを確認するために、組み込みメソッド hasRole を使用しました。 hasRole がtrueを返すと、タスクは最終リストに残ります。そのため、ユーザーが管理者の場合、ルールはリスト内のすべての項目に対してtrueを返します。したがって、最終リストにはすべての項目が含まれます。

それでは、 @ PreFilter を使用して save メソッドにパラメータとして渡されたリストをフィルタリングしましょう。

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

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

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

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

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

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

5結論

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

このGithubレポジトリ の完全なコード例を確認してください。