Präambel: Seit Spring-Security 3.2 ist @AuthenticationPrincipal
am Ende dieser Antwort eine nette Anmerkung beschrieben. Dies ist der beste Weg, wenn Sie Spring-Security> = 3.2 verwenden.
Wenn du:
- Verwenden Sie eine ältere Version von Spring-Security.
- Sie müssen Ihr benutzerdefiniertes Benutzerobjekt aus der Datenbank mit einigen Informationen (wie dem Login oder der ID) laden, die im Principal oder gespeichert sind
- wollen lernen, wie ein
HandlerMethodArgumentResolver
oder WebArgumentResolver
dies auf elegante Weise lösen kann, oder wollen einfach nur den Hintergrund hinter @AuthenticationPrincipal
und lernen AuthenticationPrincipalArgumentResolver
(weil es auf a basiert HandlerMethodArgumentResolver
)
dann lesen Sie weiter - sonst verwenden Sie einfach @AuthenticationPrincipal
und danken Sie Rob Winch (Autor von @AuthenticationPrincipal
) und Lukas Schmelzeisen (für seine Antwort).
(Übrigens: Meine Antwort ist etwas älter (Januar 2012), daher war es Lukas Schmelzeisen , der als erster die @AuthenticationPrincipal
Annotation-Lösungsbasis auf Spring Security 3.2 aufstellte .)
Dann können Sie in Ihrem Controller verwenden
public ModelAndView someRequestHandler(Principal principal) {
User activeUser = (User) ((Authentication) principal).getPrincipal();
...
}
Das ist in Ordnung, wenn Sie es einmal brauchen. Wenn Sie es jedoch mehrmals benötigen, ist es hässlich, weil es Ihren Controller mit Infrastrukturdetails verschmutzt. Dies sollte normalerweise vom Framework ausgeblendet werden.
Was Sie also wirklich wollen, ist ein Controller wie dieser:
public ModelAndView someRequestHandler(@ActiveUser User activeUser) {
...
}
Daher müssen Sie nur a implementieren WebArgumentResolver
. Es hat eine Methode
Object resolveArgument(MethodParameter methodParameter,
NativeWebRequest webRequest)
throws Exception
Das erhält die Webanforderung (zweiter Parameter) und muss die zurückgeben, User
wenn es sich für das Methodenargument (den ersten Parameter) verantwortlich fühlt.
Seit Frühjahr 3.1 gibt es ein neues Konzept namens HandlerMethodArgumentResolver
. Wenn Sie Spring 3.1+ verwenden, sollten Sie es verwenden. (Es wird im nächsten Abschnitt dieser Antwort beschrieben))
public class CurrentUserWebArgumentResolver implements WebArgumentResolver{
Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) {
if(methodParameter is for type User && methodParameter is annotated with @ActiveUser) {
Principal principal = webRequest.getUserPrincipal();
return (User) ((Authentication) principal).getPrincipal();
} else {
return WebArgumentResolver.UNRESOLVED;
}
}
}
Sie müssen die benutzerdefinierte Anmerkung definieren - Sie können sie überspringen, wenn jede Instanz des Benutzers immer aus dem Sicherheitskontext entnommen werden soll, aber niemals ein Befehlsobjekt ist.
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ActiveUser {}
In der Konfiguration müssen Sie nur Folgendes hinzufügen:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"
id="applicationConversionService">
<property name="customArgumentResolver">
<bean class="CurrentUserWebArgumentResolver"/>
</property>
</bean>
@See: Erfahren Sie, wie Sie die Argumente der Spring MVC @Controller-Methode anpassen
Wenn Sie Spring 3.1 verwenden, empfehlen sie HandlerMethodArgumentResolver gegenüber WebArgumentResolver. - siehe Kommentar von Jay
Gleiches gilt HandlerMethodArgumentResolver
für Spring 3.1+
public class CurrentUserHandlerMethodArgumentResolver
implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return
methodParameter.getParameterAnnotation(ActiveUser.class) != null
&& methodParameter.getParameterType().equals(User.class);
}
@Override
public Object resolveArgument(MethodParameter methodParameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
if (this.supportsParameter(methodParameter)) {
Principal principal = webRequest.getUserPrincipal();
return (User) ((Authentication) principal).getPrincipal();
} else {
return WebArgumentResolver.UNRESOLVED;
}
}
}
In der Konfiguration müssen Sie dies hinzufügen
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="CurrentUserHandlerMethodArgumentResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>
@Siehe Nutzung der Spring MVC 3.1 HandlerMethodArgumentResolver-Schnittstelle
Spring-Security 3.2 Lösung
Spring Security 3.2 (nicht mit Spring 3.2 verwechseln) verfügt über eine eigene integrierte Lösung: @AuthenticationPrincipal
( org.springframework.security.web.bind.annotation.AuthenticationPrincipal
). Dies ist in Lukas Schmelzeisens Antwort gut beschrieben
Es schreibt nur
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
...
}
Damit dies funktioniert, müssen Sie AuthenticationPrincipalArgumentResolver
( org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver
) registrieren : entweder durch "Aktivieren" @EnableWebMvcSecurity
oder durch Registrieren dieser Bean innerhalb mvc:argument-resolvers
- so wie ich es oben mit der Lösung von may Spring 3.1 beschrieben habe.
@ Siehe Spring Security 3.2 Referenz, Kapitel 11.2. @AuthenticationPrincipal
Spring-Security 4.0-Lösung
Es funktioniert wie die Spring 3.2-Lösung, aber in Spring 4.0 wurde das @AuthenticationPrincipal
und AuthenticationPrincipalArgumentResolver
in ein anderes Paket "verschoben":
(Aber die alten Klassen in ihren alten Paketen existieren noch, also mischen Sie sie nicht!)
Es schreibt nur
import org.springframework.security.core.annotation.AuthenticationPrincipal;
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
...
}
Damit dies funktioniert, müssen Sie ( org.springframework.security.web.method.annotation.
) registrieren AuthenticationPrincipalArgumentResolver
: entweder durch "Aktivieren" @EnableWebMvcSecurity
oder durch Registrieren dieser Bean innerhalb mvc:argument-resolvers
- so wie ich es oben mit der Lösung von may Spring 3.1 beschrieben habe.
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
@ Siehe Spring Security 5.0-Referenz, Kapitel 39.3 @AuthenticationPrincipal