Spring Security - @PreFilter und @PostFilter

Frühlingssicherheit - @PreFilter und @PostFilter

1. Überblick

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 mit@PreFilter und@PostFilter fein abgestimmte Sicherheitsregeln mithilfe der Spring Expression Language definiert werden.

2. Einführung von@PreFilter und@PostFilter

Einfach ausgedrückt sind die Anmerkungen@PreFilter und@PostFilterused to filter lists of objects, basierend auf den von uns definierten benutzerdefinierten Sicherheitsregeln.

@PostFilter definiert eine Regel zum Filtern der Rückgabeliste einer Methode nachapplying that rule to every element in the list. 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 Interfaces) verwendet werden. Wir werden sie in diesem Artikel nur für Methoden verwenden.

Diese Annotationen sind standardmäßig nicht aktiv - wir müssen sie mit den Annotationen@EnableGlobalMethodSecurity undprePostEnabled = true aktivieren - 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 ObjektfilterObject verwenden, um einen Verweis auf das bestimmte zu testende Listenelement zu erhalten.

Spring Security bietetmany other built-in objects, um sehr spezifische und genaue Regeln zu erstellen.

For example können wir mit@PreFilter prüfen, ob dieassignee-Eigenschaft einesTask-Objekts gleich dername des aktuell authentifizierten Benutzers ist:

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

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

Wenn der authentifizierte Benutzermichael ist, enthält die endgültige Liste der von derfindAll-Methode zurückgegebenen Aufgaben nur die Aufgaben, diemichael zugewiesen sind, selbst wenn der Datenbank Aufgaben zugewiesen sind jim undpam.

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

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

Wir haben die integrierte MethodehasRole verwendet, um zu überprüfen, ob der authentifizierte Benutzer die Rolle des MANAGERS hat. WennhasRole 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 einesave-Methode ü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 Beispiel von@PostFilterverwendet haben. Der Hauptunterschied besteht darin, dass die Listenelemente vor der Ausführung der Methode gefiltert werden. Auf diese Weise können wir einige Elemente aus der Liste entfernen und verhindern, dass sie in der Datenbank gespeichert werden.

Daher kannjim, der kein Manager ist, versuchen, eine Liste von Aufgaben zu speichern, von denen einigepam zugewiesen sind. Es werden jedoch nur die Aufgaben berücksichtigt, diejim zugewiesen sind, die anderen werden ignoriert.

4. Leistung auf großen Listen

@PreFilter ist wirklich cool und einfach zu verwenden, 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 derzeitpam zugewiesen sind. Wenn wir@PreFilter, verwenden, ruft die Datenbankoperation zuerst alle Aufgaben ab und durchläuft alle, um diejenigen herauszufiltern, die nichtpam zugewiesen sind.

5. Fazit

In diesem kurzen Artikel wurde erläutert, wie Sie eine einfache, aber sichere Anwendung mit den Anmerkungen@PreFilterund@PostFiltervon Spring Security erstellen.

Überprüfen Sie das vollständige Codebeispielin this Github repository.