Preambolo: da Spring-Security 3.2 c'è una bella annotazione @AuthenticationPrincipal
descritta alla fine di questa risposta. Questo è il modo migliore per utilizzare Spring-Security> = 3.2.
Quando tu:
- utilizzare una versione precedente di Spring-Security,
- è necessario caricare l'oggetto utente personalizzato dal database mediante alcune informazioni (come il login o l'id) archiviate nell'oggetto principale o
- vuoi imparare come a
HandlerMethodArgumentResolver
o WebArgumentResolver
puoi risolverlo in modo elegante, o semplicemente vuoi imparare lo sfondo dietro @AuthenticationPrincipal
e AuthenticationPrincipalArgumentResolver
(perché è basato su a HandlerMethodArgumentResolver
)
poi continua a leggere - altrimenti usa @AuthenticationPrincipal
e ringrazia solo Rob Winch (autore di @AuthenticationPrincipal
) e Lukas Schmelzeisen (per la sua risposta).
(A proposito: la mia risposta è un po 'più vecchia (gennaio 2012), quindi è stato Lukas Schmelzeisen a presentarsi come il primo con la @AuthenticationPrincipal
soluzione di annotazione basata su Spring Security 3.2.)
Quindi è possibile utilizzare nel controller
public ModelAndView someRequestHandler(Principal principal) {
User activeUser = (User) ((Authentication) principal).getPrincipal();
...
}
Va bene se ne hai bisogno una volta. Ma se ne hai bisogno più volte è brutto perché inquina il tuo controller con i dettagli dell'infrastruttura, che normalmente dovrebbe essere nascosto dal framework.
Quindi quello che potresti davvero desiderare è avere un controller come questo:
public ModelAndView someRequestHandler(@ActiveUser User activeUser) {
...
}
Pertanto è sufficiente implementare a WebArgumentResolver
. Ha un metodo
Object resolveArgument(MethodParameter methodParameter,
NativeWebRequest webRequest)
throws Exception
Questo ottiene la richiesta web (secondo parametro) e deve restituire User
if se si sente responsabile dell'argomento del metodo (il primo parametro).
Dalla primavera 3.1 esiste un nuovo concetto chiamato HandlerMethodArgumentResolver
. Se usi Spring 3.1+, dovresti usarlo. (È descritto nella prossima sezione di questa risposta))
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;
}
}
}
È necessario definire l'annotazione personalizzata: è possibile ignorarla se ogni istanza dell'utente deve essere sempre presa dal contesto di sicurezza, ma non è mai un oggetto comando.
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ActiveUser {}
Nella configurazione devi solo aggiungere questo:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"
id="applicationConversionService">
<property name="customArgumentResolver">
<bean class="CurrentUserWebArgumentResolver"/>
</property>
</bean>
@Vedi: impara a personalizzare gli argomenti del metodo Spring MVC @Controller
Va notato che se si utilizza Spring 3.1, raccomandano HandlerMethodArgumentResolver su WebArgumentResolver. - vedi commento di Jay
Lo stesso con HandlerMethodArgumentResolver
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;
}
}
}
Nella configurazione, è necessario aggiungere questo
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="CurrentUserHandlerMethodArgumentResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>
@Vedi Sfruttare l'interfaccia Spring MVC 3.1 HandlerMethodArgumentResolver
Soluzione Spring-Security 3.2
Spring Security 3.2 (non confondere con Spring 3.2) ha la propria soluzione build in: @AuthenticationPrincipal
( org.springframework.security.web.bind.annotation.AuthenticationPrincipal
). Questo è ben descritto nella risposta di Lukas Schmelzeisen
Sta solo scrivendo
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
...
}
Per farlo funzionare è necessario registrare il AuthenticationPrincipalArgumentResolver
( org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver
): "attivando" @EnableWebMvcSecurity
o registrando questo bean all'interno mvc:argument-resolvers
- allo stesso modo in cui l'ho descritto con la soluzione Spring 3.1 sopra.
@Vedi Riferimenti su Spring Security 3.2, capitolo 11.2. @AuthenticationPrincipal
Soluzione Spring-Security 4.0
Funziona come la soluzione di 3.2 primavera, ma in Spring 4.0 la @AuthenticationPrincipal
e AuthenticationPrincipalArgumentResolver
è stato "trasferito" a un altro pacchetto:
(Ma le vecchie classi nei suoi vecchi pacchetti esistono ancora, quindi non mescolarle!)
Sta solo scrivendo
import org.springframework.security.core.annotation.AuthenticationPrincipal;
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
...
}
Per farlo funzionare è necessario registrare il ( org.springframework.security.web.method.annotation.
) AuthenticationPrincipalArgumentResolver
: "attivando" @EnableWebMvcSecurity
o registrando questo bean all'interno mvc:argument-resolvers
- allo stesso modo in cui l'ho descritto con la soluzione Spring 3.1 sopra.
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
@Vedere Riferimenti a Spring Security 5.0, Capitolo 39.3 @AuthenticationPrincipal