Frühlingssicherheit - @PreFilter und @PostFilter

1. Übersicht

In diesem Artikel erfahren Sie, wie Sie die Annotationen @PreFilter und @PostFilter verwenden , um Vorgänge in einer Spring-Anwendung zu sichern.

In Verbindung mit den authentifizierten Hauptinformationen können wir mit @PreFilter und @PostFilter fein abgestimmte Sicherheitsregeln mithilfe von Spring Expression Language definieren.

2. Einführung in @PreFilter und @PostFilter

Einfach ausgedrückt, werden die Annotationen @PreFilter und @PostFilter verwendet, um Listen von Objekten basierend auf benutzerdefinierten Sicherheitsregeln zu filtern, die wir definieren.

@PostFilter definiert eine Regel zum Filtern der Rückgabeliste einer Methode, indem diese Regel auf jedes Element in der Liste angewendet wird . Wenn der ausgewertete Wert wahr ist, wird das Element in der Liste beibehalten. Andernfalls wird der Artikel entfernt.

@PreFilter funktioniert auf sehr ähnliche Weise. Die Filterung wird jedoch auf eine Liste angewendet, die als Eingabeparameter an die mit Anmerkungen versehene Methode übergeben wird.

Beide Annotationen können für Methoden oder Typen (Klassen und Schnittstellen) verwendet werden. Wir werden sie in diesem Artikel nur für Methoden verwenden.

Thesen Anmerkungen sind nicht standardmäßig aktiv - wir werden sie mit dem ermöglichen , müssen @EnableGlobalMethodSecurity Annotation und prePostEnabled = true - in unserer Sicherheitskonfiguration:

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

3. Sicherheitsregeln schreiben

Um die Sicherheitsregeln in diese beiden Anmerkungen zu schreiben, verwenden wir Spring-EL-Ausdrücke. Wir können auch das integrierte Objekt filterObject verwenden , um einen Verweis auf das bestimmte zu testende Listenelement zu erhalten.

Spring Security bietet viele andere integrierte Objekte, um sehr spezifische und genaue Regeln zu erstellen.

Zum Beispiel können wir verwenden @PreFilter zu überprüfen , ob der Zessionar Eigenschaft eines Task - Objekt ist gleich dem Namen des aktuell authentifizierte Benutzer:

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

Wir haben hier die Annotation @PostFilter verwendet , da die Methode zuerst alle Aufgaben ausführen und abrufen soll und jede einzelne Aufgabe aus der Liste über unsere Filterregel übergeben wird.

Also, wenn der authentifizierte Benutzer ist michael , die endgültige Liste der Aufgaben , die von der zurück findAll Methode würde nur die Aufgaben enthalten, die zugeordnet sind , michael , selbst wenn die Datenbank Aufgaben zugewiesen hat jim und pam .

Lassen Sie uns nun die Regel etwas interessanter machen. Angenommen, ein Benutzer, der ein Manager ist, kann alle Aufgaben anzeigen, unabhängig davon, wem er zugewiesen ist:

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

Wir haben die integrierte Methode hasRole verwendet , um zu überprüfen, ob der authentifizierte Benutzer die Rolle des MANAGERS hat. Wenn hasRole true zurückgibt, wird die Aufgabe in der endgültigen Liste beibehalten. Wenn der Benutzer ein Manager ist, gibt die Regel für jedes Element in der Liste true zurück. Somit enthält die endgültige Liste alle Elemente.

Filtern wir nun eine Liste, die als Parameter an eine Speichermethode übergeben wurde , mit @PreFilter :

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

Die Sicherheitsregel ist dieselbe wie die, die wir im @ PostFilter- Beispiel verwendet haben. Der Hauptunterschied besteht darin, dass die Listenelemente gefiltert werden, bevor die Methode ausgeführt wird. Auf diese Weise können wir einige Elemente aus der Liste entfernen und verhindern, dass sie in der Datenbank gespeichert werden.

So jim , der kein Manager ist, kann versuchen, eine Liste von Aufgaben zu speichern, von denen einige zugeordnet sind pam . Es werden jedoch nur die Aufgaben enthalten, die Jim zugewiesen wurden , die anderen werden ignoriert.

4. Leistung auf großen Listen

@PreFilter ist wirklich cool und einfach zu bedienen, kann jedoch bei sehr großen Listen ineffizient sein, da beim Abrufen alle Daten abgerufen und der Filter anschließend angewendet werden.

Stellen Sie sich zum Beispiel vor, wir haben Tausende von Aufgaben in unserer Datenbank und möchten die fünf Aufgaben abrufen, die pam derzeit zugewiesen sind . Wenn wir verwenden @PreFilter , wird die Datenbankoperation alle Aufgaben holen erste, und durchlaufen sie alle diejenigen herausgefiltert werden , die nicht zugeordnet sind pam .

5. Schlussfolgerung

In diesem kurzen Artikel wurde erläutert, wie Sie mit den Annotationen @PreFilter und @PostFilter von Spring Security eine einfache, aber sichere Anwendung erstellen .

Überprüfen Sie das vollständige Codebeispiel in diesem Github-Repository.