Preámbulo: desde Spring-Security 3.2 hay una buena anotación @AuthenticationPrincipal
descrita al final de esta respuesta. Esta es la mejor manera de usar Spring-Security> = 3.2.
Cuando usted:
- use una versión anterior de Spring-Security,
- necesita cargar su objeto de usuario personalizado de la base de datos mediante alguna información (como el inicio de sesión o la identificación) almacenada en el principal o
- desee aprender una
HandlerMethodArgumentResolver
o WebArgumentResolver
puede solucionar esto de una manera elegante, o simplemente quieren aprender un segundo plano detrás @AuthenticationPrincipal
y AuthenticationPrincipalArgumentResolver
(debido a que se basa en una HandlerMethodArgumentResolver
)
luego siga leyendo; de lo contrario, solo use @AuthenticationPrincipal
y agradezca a Rob Winch (Autor de @AuthenticationPrincipal
) y Lukas Schmelzeisen (por su respuesta).
(Por cierto: mi respuesta es un poco más antigua (enero de 2012), por lo que fue Lukas Schmelzeisen quien surgió como el primero con la @AuthenticationPrincipal
solución de anotación basada en Spring Security 3.2.)
Entonces puedes usar en tu controlador
public ModelAndView someRequestHandler(Principal principal) {
User activeUser = (User) ((Authentication) principal).getPrincipal();
...
}
Eso está bien si lo necesitas una vez. Pero si lo necesita varias veces es feo porque contamina su controlador con detalles de infraestructura, eso normalmente debería estar oculto por el marco.
Entonces, lo que realmente puede desear es tener un controlador como este:
public ModelAndView someRequestHandler(@ActiveUser User activeUser) {
...
}
Por lo tanto, solo necesita implementar a WebArgumentResolver
. Tiene un metodo
Object resolveArgument(MethodParameter methodParameter,
NativeWebRequest webRequest)
throws Exception
Eso obtiene la solicitud web (segundo parámetro) y debe devolver el User
si se siente responsable del argumento del método (el primer parámetro).
Desde la primavera 3.1 hay un nuevo concepto llamado HandlerMethodArgumentResolver
. Si usa Spring 3.1+, entonces debe usarlo. (Se describe en la siguiente sección de esta respuesta))
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;
}
}
}
Debe definir la anotación personalizada: puede omitirla si cada instancia de usuario siempre debe tomarse del contexto de seguridad, pero nunca es un objeto de comando.
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ActiveUser {}
En la configuración solo necesita agregar esto:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"
id="applicationConversionService">
<property name="customArgumentResolver">
<bean class="CurrentUserWebArgumentResolver"/>
</property>
</bean>
@Ver: aprenda a personalizar los argumentos del método Spring MVC @Controller
Cabe señalar que si está utilizando Spring 3.1, recomiendan HandlerMethodArgumentResolver sobre WebArgumentResolver. - ver comentario de Jay
Lo mismo 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;
}
}
}
En la configuración, debe agregar esto
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="CurrentUserHandlerMethodArgumentResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>
@Ver Aprovechar la interfaz Spring MVC 3.1 HandlerMethodArgumentResolver
Solución Spring-Security 3.2
Spring Security 3.2 (no confundir con Spring 3.2) tiene su propia solución integrada: @AuthenticationPrincipal
( org.springframework.security.web.bind.annotation.AuthenticationPrincipal
). Esto se describe muy bien en la respuesta de Lukas Schmelzeisen
Es solo escribir
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
...
}
Para que esto funcione, debe registrar el AuthenticationPrincipalArgumentResolver
( org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver
): ya sea "activando" @EnableWebMvcSecurity
o registrando este bean dentro mvc:argument-resolvers
, de la misma manera que lo describí con la solución Spring 3.1 anterior.
@ Consulte Spring Security 3.2 Reference, Capítulo 11.2. @AuthenticationPrincipal
Solución Spring-Security 4.0
Funciona como la solución Spring 3.2, pero en Spring 4.0 el @AuthenticationPrincipal
y AuthenticationPrincipalArgumentResolver
fue "movido" a otro paquete:
(Pero las clases antiguas en sus paquetes anteriores todavía existen, ¡así que no las mezcle!)
Es solo escribir
import org.springframework.security.core.annotation.AuthenticationPrincipal;
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
...
}
Para que esto funcione, debe registrar el ( org.springframework.security.web.method.annotation.
) AuthenticationPrincipalArgumentResolver
: ya sea "activando" @EnableWebMvcSecurity
o registrando este bean dentro mvc:argument-resolvers
, de la misma manera que lo describí con la solución Spring 3.1 anterior.
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
@ Consulte Spring Security 5.0 Reference, Capítulo 39.3 @AuthenticationPrincipal