Servlet 3 Async Support mit Spring MVC und Spring Security
1. Einführung
In diesem kurzen Tutorial konzentrieren wir uns aufthe Servlet 3 support for async requests, and how Spring MVC and Spring Security handle these.
Die grundlegendste Motivation für Asynchronität in Webanwendungen ist die Bearbeitung von Anfragen mit langer Laufzeit. In den meisten Anwendungsfällen müssen wir sicherstellen, dass das Spring Security-Prinzipal an diese Threads weitergegeben wird.
Und natürlich liegt Spring Securityintegrates with @Asyncaußerhalb des Bereichs von MVC und verarbeitet auch HTTP-Anforderungen.
2. Maven-Abhängigkeiten
Um die asynchrone Integration in Spring MVC verwenden zu können, müssen die folgenden Abhängigkeiten in unserepom.xml aufgenommen werden:
org.springframework.security
spring-security-web
4.2.1.RELEASE
org.springframework.security
spring-security-config
4.2.1.RELEASE
Die neueste Version der Spring Security-Abhängigkeiten finden Sie inhere.
3. Feder MVC und@Async
Gemäß den offiziellendocs integriert sich Spring Security inWebAsyncManager.
Der erste Schritt besteht darin, sicherzustellen, dass unserespringSecurityFilterChain für die Verarbeitung asynchroner Anforderungen eingerichtet sind. Wir können dies entweder in der Java-Konfiguration tun, indem wir der KonfigurationsklasseServletdie folgende Zeile hinzufügen:
dispatcher.setAsyncSupported(true);
oder in XML config:
springSecurityFilterChain
org.springframework.web.filter.DelegatingFilterProxy
true
springSecurityFilterChain
/*
REQUEST
ASYNC
Wir müssen auch den Parameterasync-supported in unserer Servlet-Konfiguration aktivieren:
...
true
...
Jetzt können wir asynchrone Anforderungen mitSecurityContext senden, die mit ihnen weitergegeben werden.
Interne Mechanismen in Spring Security stellen sicher, dass unsereSecurityContext nicht mehr gelöscht werden, wenn eine Antwort in weiterenThread festgeschrieben wird, was zu einer Benutzerabmeldung führt.
4. Anwendungsfälle
Lassen Sie uns dies anhand eines einfachen Beispiels in Aktion sehen:
@Override
public Callable checkIfPrincipalPropagated() {
Object before
= SecurityContextHolder.getContext().getAuthentication().getPrincipal();
log.info("Before new thread: " + before);
return new Callable() {
public Boolean call() throws Exception {
Object after
= SecurityContextHolder.getContext().getAuthentication().getPrincipal();
log.info("New thread: " + after);
return before == after;
}
};
}
Wir wollen überprüfen, ob die FederSecurityContext an den neuen Thread weitergegeben wird.
Bei der oben vorgestellten Methode werdenCallable automatisch mit den enthaltenenSecurityContext ausgeführt, wie in den Protokollen dargestellt:
web - 2017-01-02 10:42:19,011 [http-nio-8081-exec-3] INFO
o.example.web.service.AsyncService - Before new thread:
[email protected]:
Username: temporary; Password: [PROTECTED]; Enabled: true;
AccountNonExpired: true; credentialsNonExpired: true;
AccountNonLocked: true; Granted Authorities: ROLE_ADMIN
web - 2017-01-02 10:42:19,020 [MvcAsync1] INFO
o.example.web.service.AsyncService - New thread:
[email protected]:
Username: temporary; Password: [PROTECTED]; Enabled: true;
AccountNonExpired: true; credentialsNonExpired: true;
AccountNonLocked: true; Granted Authorities: ROLE_ADMIN
Ohne dieSecurityContext einzurichten, die weitergegeben werden sollen, erhält die zweite Anforderung den Wertnull.
Es gibt auch andere wichtige Anwendungsfälle für die Verwendung asynchroner Anforderungen mit propagiertenSecurityContext:
-
Wir möchten mehrere externe Anforderungen erstellen, die parallel ausgeführt werden können und deren Ausführung möglicherweise viel Zeit in Anspruch nimmt
-
Wir müssen einige wichtige Vorgänge lokal ausführen, und unsere externe Anforderung kann parallel dazu ausgeführt werden
-
Andere stellen Feuer-und-Vergessen-Szenarien dar, wie zum Beispiel das Senden einer E-Mail
Beachten Sie, dass die Konvertierung dieser in einen asynchronen Ansatz möglicherweise Synchronisierungsergebnisse erfordert, wenn unsere mehreren Methodenaufrufe zuvor synchron miteinander verkettet waren.
5. Fazit
In diesem kurzen Tutorial haben wir die Spring-Unterstützung für die Verarbeitung asynchroner Anforderungen in einem authentifizierten Kontext. veranschaulicht
Aus Sicht des Programmiermodells erscheinen die neuen Funktionen täuschend einfach. Aber es gibt sicherlich einige Aspekte, die ein tieferes Verständnis erfordern.
Dieses Beispiel ist auch als Maven-Projektover on Github verfügbar.