46 Method Level Security

Method Level Security in Spring Boot erlaubt es, Sicherheitsaspekte auf der Ebene von Methoden zu definieren. Mit dieser Funktionalität können Sie den Zugriff auf bestimmte Funktionen Ihrer Anwendung basierend auf Rollen, Berechtigungen oder anderen Sicherheitskriterien beschränken. In Spring Boot wird dies hauptsächlich durch die Integration von Spring Security erreicht, das verschiedene Sicherheitsanmerkungen wie @PreAuthorize, @Secured, und @RolesAllowed bereitstellt.

In diesem Kapitel erklären wir, wie Sie Method Level Security in Spring Boot aktivieren und verwenden können, um den Zugriff auf Ihre RESTful Services zu kontrollieren.

46.1 Voraussetzungen

Um Method Level Security in Spring Boot zu nutzen, müssen Sie Spring Security in Ihrem Projekt integrieren. Fügen Sie die folgende Abhängigkeit in Ihrer pom.xml hinzu, wenn Sie dies noch nicht getan haben:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

46.2 Aktivieren der Method Level Security

Bevor Sie Method Level Security verwenden können, müssen Sie diese in Ihrer Spring Boot-Anwendung aktivieren. Dies geschieht durch die Annotation @EnableGlobalMethodSecurity, die auf einer Konfigurationsklasse verwendet wird. Sie ermöglicht es, Anmerkungen auf Methodenebene zu verwenden, um Sicherheitsregeln zu definieren.

46.2.1 Beispiel: Aktivieren von Method Level Security

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig {
    // Sicherheitskonfiguration
}

In diesem Beispiel aktivieren wir drei Arten der Method Level Security: - prePostEnabled = true: Ermöglicht die Verwendung von @PreAuthorize und @PostAuthorize. - securedEnabled = true: Ermöglicht die Verwendung von @Secured. - jsr250Enabled = true: Ermöglicht die Verwendung von @RolesAllowed.

46.3 Verwendung von @PreAuthorize

Die Annotation @PreAuthorize prüft, ob ein bestimmter Ausdruck vor der Ausführung einer Methode wahr ist. Sie ist äußerst flexibel und ermöglicht die Definition komplexer Sicherheitsregeln, wie z.B. den Zugriff basierend auf Benutzerrollen oder bestimmten Attributen eines Objekts.

46.3.1 Beispiel: Zugriff basierend auf Benutzerrollen

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProductController {

    @GetMapping("/admin/products")
    @PreAuthorize("hasRole('ADMIN')")
    public String getAdminProducts() {
        return "Liste der Admin-Produkte";
    }

    @GetMapping("/user/products")
    @PreAuthorize("hasRole('USER')")
    public String getUserProducts() {
        return "Liste der Benutzer-Produkte";
    }
}

In diesem Beispiel darf nur ein Benutzer mit der Rolle ADMIN auf den Endpunkt /admin/products zugreifen, während ein Benutzer mit der Rolle USER auf den Endpunkt /user/products zugreifen kann.

46.3.2 Beispiel: Zugriff basierend auf Attributen eines Objekts

Sie können auch den Zugriff auf Methoden basierend auf Attributen des übergebenen Objekts einschränken. Dies ist nützlich, wenn Sie sicherstellen möchten, dass nur der Eigentümer eines bestimmten Objekts darauf zugreifen kann.

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderController {

    @GetMapping("/orders/{orderId}")
    @PreAuthorize("#orderId == authentication.principal.id")
    public String getOrder(@PathVariable Long orderId) {
        return "Bestellung mit der ID " + orderId;
    }
}

In diesem Beispiel wird die Bestellung nur dann zurückgegeben, wenn die orderId mit der ID des aktuell authentifizierten Benutzers übereinstimmt.

46.4 Verwendung von @Secured

Die Annotation @Secured bietet eine einfachere Möglichkeit, den Zugriff auf Methoden auf Basis von Rollen einzuschränken. Im Gegensatz zu @PreAuthorize erlaubt @Secured nur die Prüfung von Rollen und nicht von komplexen Ausdrücken.

46.4.1 Beispiel: Verwendung von @Secured

import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProductController {

    @GetMapping("/admin/products")
    @Secured("ROLE_ADMIN")
    public String getAdminProducts() {
        return "Liste der Admin-Produkte";
    }
}

In diesem Beispiel wird der Zugriff auf die Methode getAdminProducts() nur Benutzern mit der Rolle ROLE_ADMIN gewährt.

46.5 Verwendung von @RolesAllowed

Die Annotation @RolesAllowed ist Teil der JSR-250-Spezifikation und funktioniert ähnlich wie @Secured, um den Zugriff auf Basis von Rollen zu steuern. Sie wird hauptsächlich verwendet, wenn Sie eine JSR-250-konforme Methode zur Rollenprüfung implementieren möchten.

46.5.1 Beispiel: Verwendung von @RolesAllowed

import javax.annotation.security.RolesAllowed;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProductController {

    @GetMapping("/admin/products")
    @RolesAllowed("ROLE_ADMIN")
    public String getAdminProducts() {
        return "Liste der Admin-Produkte";
    }
}

In diesem Beispiel darf nur ein Benutzer mit der Rolle ROLE_ADMIN auf den /admin/products-Endpunkt zugreifen.

46.6 Verwendung von @PostAuthorize

Die Annotation @PostAuthorize funktioniert ähnlich wie @PreAuthorize, jedoch wird sie erst nach der Ausführung der Methode aufgerufen. Sie ist nützlich, wenn Sie den Rückgabewert der Methode basierend auf Sicherheitskriterien überprüfen möchten.

46.6.1 Beispiel: Verwendung von @PostAuthorize

import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderController {

    @GetMapping("/orders/{orderId}")
    @PostAuthorize("returnObject.userId == authentication.principal.id")
    public Order getOrder(@PathVariable Long orderId) {
        // Ruft die Bestellung aus der Datenbank ab
        Order order = orderService.findById(orderId);
        return order;
    }
}

In diesem Beispiel wird die Methode getOrder() immer ausgeführt, aber der Rückgabewert (das Order-Objekt) wird nach der Ausführung überprüft, um sicherzustellen, dass die userId der Bestellung mit der ID des aktuell authentifizierten Benutzers übereinstimmt.

46.7 tl;dr

Method Level Security in Spring Boot bietet eine leistungsstarke und flexible Möglichkeit, den Zugriff auf REST-Services auf der Ebene einzelner Methoden zu steuern. Mit Anmerkungen wie @PreAuthorize, @Secured, @RolesAllowed und @PostAuthorize können Sie Sicherheitsregeln definieren, die von einfachen Rollenprüfungen bis hin zu komplexeren Ausdrücken reichen. Diese Sicherheitsmechanismen bieten eine feingranulare Kontrolle über den Zugriff auf geschützte Ressourcen und tragen dazu bei, Ihre Anwendung sicherer und robuster zu machen.