Spring Boot Authentication-Überwachungsunterstützung

Unterstützung der Spring Boot-Authentifizierungsprüfung

1. Überblick

In diesem kurzen Artikel werden das Spring Boot Actuator-Modul und die Unterstützung für das Veröffentlichen von Authentifizierungs- und Autorisierungsereignissen in Verbindung mit Spring Security erläutert.

2. Maven-Abhängigkeiten

Zuerst müssen wir diespring-boot-starter-actuator zu unserenpom.xml: hinzufügen


    org.springframework.boot
    spring-boot-starter-actuator
    2.1.7.RELEASE

Die neueste Version ist im Repository vonMaven Centralverfügbar.

3. Abhören von Authentifizierungs- und Autorisierungsereignissen

Um alle Authentifizierungs- und Autorisierungsversuche in einer Spring Boot-Anwendung zu protokollieren, können Sie einfach eine Bean mit einer Listener-Methode definieren:

@Component
public class LoginAttemptsLogger {

    @EventListener
    public void auditEventHappened(
      AuditApplicationEvent auditApplicationEvent) {

        AuditEvent auditEvent = auditApplicationEvent.getAuditEvent();
        System.out.println("Principal " + auditEvent.getPrincipal()
          + " - " + auditEvent.getType());

        WebAuthenticationDetails details =
          (WebAuthenticationDetails) auditEvent.getData().get("details");
        System.out.println("Remote IP address: "
          + details.getRemoteAddress());
        System.out.println("  Session Id: " + details.getSessionId());
    }
}

Beachten Sie, dass wir nur einige der inAuditApplicationEvent verfügbaren Elemente ausgeben, um anzuzeigen, welche Informationen verfügbar sind. In einer tatsächlichen Anwendung möchten Sie diese Informationen möglicherweise in einem Repository oder Cache speichern, um sie weiter zu verarbeiten.

Beachten Sie, dass jede Springbohne funktioniert. Die Grundlagen der neuen Spring-Event-Unterstützung sind ganz einfach:

  • Kommentieren Sie die Methode mit@EventListener

  • Fügen SieAuditApplicationEvent als einziges Argument der Methode hinzu

Die Ausgabe der Anwendung sieht ungefähr so ​​aus:

Principal anonymousUser - AUTHORIZATION_FAILURE
  Remote IP address: 0:0:0:0:0:0:0:1
  Session Id: null
Principal user - AUTHENTICATION_FAILURE
  Remote IP address: 0:0:0:0:0:0:0:1
  Session Id: BD41692232875A5A65C5E35E63D784F6
Principal user - AUTHENTICATION_SUCCESS
  Remote IP address: 0:0:0:0:0:0:0:1
  Session Id: BD41692232875A5A65C5E35E63D784F6

In diesem Beispiel wurden dreiAuditApplicationEvents vom Listener empfangen:

  1. Ohne Anmeldung wurde der Zugriff auf eine eingeschränkte Seite angefordert

  2. Beim Anmelden wurde ein falsches Passwort verwendet

  3. Beim zweiten Mal wurde ein korrektes Passwort verwendet

4. Ein Authentication Audit Listener

Wenn die vonAuthorizationAuditListener von Spring Boot bereitgestellten Informationen nicht ausreichen, können Siecreate your own bean to expose more information. verwenden

Schauen wir uns ein Beispiel an, in dem wir auch die Anforderungs-URL offenlegen, auf die zugegriffen wurde, als die Autorisierung fehlschlug:

@Component
public class ExposeAttemptedPathAuthorizationAuditListener
  extends AbstractAuthorizationAuditListener {

    public static final String AUTHORIZATION_FAILURE
      = "AUTHORIZATION_FAILURE";

    @Override
    public void onApplicationEvent(AbstractAuthorizationEvent event) {
        if (event instanceof AuthorizationFailureEvent) {
            onAuthorizationFailureEvent((AuthorizationFailureEvent) event);
        }
    }

    private void onAuthorizationFailureEvent(
      AuthorizationFailureEvent event) {
        Map data = new HashMap<>();
        data.put(
          "type", event.getAccessDeniedException().getClass().getName());
        data.put("message", event.getAccessDeniedException().getMessage());
        data.put(
          "requestUrl", ((FilterInvocation)event.getSource()).getRequestUrl() );

        if (event.getAuthentication().getDetails() != null) {
            data.put("details",
              event.getAuthentication().getDetails());
        }
        publish(new AuditEvent(event.getAuthentication().getName(),
          AUTHORIZATION_FAILURE, data));
    }
}

Wir können jetzt die Anforderungs-URL in unserem Listener protokollieren:

@Component
public class LoginAttemptsLogger {

    @EventListener
    public void auditEventHappened(
      AuditApplicationEvent auditApplicationEvent) {
        AuditEvent auditEvent = auditApplicationEvent.getAuditEvent();

        System.out.println("Principal " + auditEvent.getPrincipal()
          + " - " + auditEvent.getType());

        WebAuthenticationDetails details
          = (WebAuthenticationDetails) auditEvent.getData().get("details");

        System.out.println("  Remote IP address: "
          + details.getRemoteAddress());
        System.out.println("  Session Id: " + details.getSessionId());
        System.out.println("  Request URL: "
          + auditEvent.getData().get("requestUrl"));
    }
}

Folglich enthält die Ausgabe jetzt die angeforderte URL:

Principal anonymousUser - AUTHORIZATION_FAILURE
  Remote IP address: 0:0:0:0:0:0:0:1
  Session Id: null
  Request URL: /hello

Beachten Sie, dass wir in diesem Beispiel das abstrakteAbstractAuthorizationAuditListener erweitert haben, damit wir in unserer Implementierung diepublish-Methode dieser Basisklasse verwenden können.

Wenn Sie es testen möchten, überprüfen Sie den Quellcode und führen Sie Folgendes aus:

mvn clean spring-boot:run

Danach können Sie Ihren Browser aufhttp://localhost:8080/ richten.

5. Speichern von Überwachungsereignissen

Standardmäßig speichert Spring Boot die Überwachungsereignisse inAuditEventRepository. Wenn Sie keine Bean mit einer eigenen Implementierung erstellen, wird einInMemoryAuditEventRepository für Sie verkabelt.

InMemoryAuditEventRepository ist eine Art Umlaufpuffer, in dem die letzten 4000 Überwachungsereignisse gespeichert werden. Auf diese Ereignisse kann dann über den Verwaltungsendpunkthttp://localhost:8080/auditevents zugegriffen werden.

Dies gibt eine JSON-Darstellung der Überwachungsereignisse zurück:

{
  "events": [
    {
      "timestamp": "2017-03-09T19:21:59+0000",
      "principal": "anonymousUser",
      "type": "AUTHORIZATION_FAILURE",
      "data": {
        "requestUrl": "/auditevents",
        "details": {
          "remoteAddress": "0:0:0:0:0:0:0:1",
          "sessionId": null
        },
        "type": "org.springframework.security.access.AccessDeniedException",
        "message": "Access is denied"
      }
    },
    {
      "timestamp": "2017-03-09T19:22:00+0000",
      "principal": "anonymousUser",
      "type": "AUTHORIZATION_FAILURE",
      "data": {
        "requestUrl": "/favicon.ico",
        "details": {
          "remoteAddress": "0:0:0:0:0:0:0:1",
          "sessionId": "18FA15865F80760521BBB736D3036901"
        },
        "type": "org.springframework.security.access.AccessDeniedException",
        "message": "Access is denied"
      }
    },
    {
      "timestamp": "2017-03-09T19:22:03+0000",
      "principal": "user",
      "type": "AUTHENTICATION_SUCCESS",
      "data": {
        "details": {
          "remoteAddress": "0:0:0:0:0:0:0:1",
          "sessionId": "18FA15865F80760521BBB736D3036901"
        }
      }
    }
  ]
}

6. Fazit

Mit der Aktorunterstützung in Spring Boot wird es einfach, die Authentifizierungs- und Autorisierungsversuche von Benutzern zu protokollieren. Der Leser wird für einige zusätzliche Informationen auch aufproduction ready auditing verwiesen.

Der Code aus diesem Artikel istover on GitHub.