在我的控制器中,当我需要活动(登录)用户时,我正在执行以下操作以获取UserDetails实现:
User activeUser = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal(); log.debug(activeUser.getSomeCustomField());
它工作正常,但我认为Spring在这种情况下可以使生活更轻松。有没有办法将UserDetails自动接线连接到控制器或方法中?
UserDetails
例如,类似:
public ModelAndView someRequestHandler(Principal principal) { ... }
但是UsernamePasswordAuthenticationToken我得到了,UserDetails而不是得到了?
UsernamePasswordAuthenticationToken
我正在寻找一种优雅的解决方案。有任何想法吗?
序言:从Spring-Security 3.2开始@AuthenticationPrincipal,此答案的末尾描述了一个不错的注释。当你使用Spring-Security> = 3.2时,这是最好的方法。
@AuthenticationPrincipal
当你:
a HandlerMethodArgumentResolver
WebArgumentResolver
@AuthenticationPrincipaland
AuthenticationPrincipalArgumentResolver
HandlerMethodArgumentResolver)
(顺便说一句:我的回答有点老(2012年1月),因此是Lukas Schmelzeisen作为第一个使用@AuthenticationPrincipal基于Spring Security 3.2 的注释解决方案的人。)
然后你可以在控制器中使用
public ModelAndView someRequestHandler(Principal principal) { User activeUser = (User) ((Authentication) principal).getPrincipal(); ... }
如果你需要一次,那没关系。但是,如果你因其丑陋的原因而需要它的几倍,因为它会污染你的控制器的基础结构详细信息,则通常应将其隐藏在框架中。
因此,你可能真正想要的是拥有这样的控制器:
public ModelAndView someRequestHandler(@ActiveUser User activeUser) { ... }
因此,你只需要实现即可WebArgumentResolver。它有一种方法
Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws Exception
这将获取Web请求(第二个参数),并且User如果感觉对方法参数(第一个参数)负责,则必须返回。
从Spring 3.1开始,有一个新概念称为HandlerMethodArgumentResolver。如果使用Spring 3.1+,则应该使用它。(此答案的下一部分对此进行了说明)
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; } } }
你需要定义自定义注释-如果应始终从安全上下文中获取User的每个实例,但绝不要将其作为命令对象,则可以跳过它。
@Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ActiveUser {}
在配置中,你只需要添加以下内容:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" id="applicationConversionService"> <property name="customArgumentResolver"> <bean class="CurrentUserWebArgumentResolver"/> </property> </bean>
应该注意的是,如果你使用的是Spring 3.1,他们建议使用HandlerMethodArgumentResolver而不是WebArgumentResolver。-见周杰伦的评论
与HandlerMethodArgumentResolverSpring 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; } } }
在配置中,你需要添加此
<mvc:annotation-driven> <mvc:argument-resolvers> <bean class="CurrentUserHandlerMethodArgumentResolver"/> </mvc:argument-resolvers> </mvc:annotation-driven>
Spring-Security 3.2解决方案
spring安全3.2(不使用Spring 3.2混淆)在溶液中有自己的编译:@AuthenticationPrincipal(org.springframework.security.web.bind.annotation.AuthenticationPrincipal)。Lukas Schmelzeisen的回答对此进行了很好的描述。
@AuthenticationPrincipal(org.springframework.security.web.bind.annotation.AuthenticationPrincipal)。Lukas Schmelzeisen
只是在写
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) { ... }
要使此工作正常进行,你需要注册AuthenticationPrincipalArgumentResolver(org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver):通过“激活”@EnableWebMvcSecurity或在其中注册此Bean,mvc:argument-resolvers这与我在上面的Spring 3.1解决方案中描述的方式相同。
AuthenticationPrincipalArgumentResolver(org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver)
@EnableWebMvcSecurity
Bean,mvc:argument-resolvers
@请参阅《Spring Security 3.2参考》的第11.2章。@AuthenticationPrincipal
Spring-Security 4.0解决方案
它的工作方式类似于Spring 3.2解决方案,但在Spring 4.0中,@AuthenticationPrincipal和AuthenticationPrincipalArgumentResolver被“移动”到另一个软件包中:
(但是旧包中的旧类仍然存在,因此请不要混合使用!)
import org.springframework.security.core.annotation.AuthenticationPrincipal; ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) { ... }
要使此工作正常进行,你需要注册(org.springframework.security.web.method.annotation.)AuthenticationPrincipalArgumentResolver:通过“激活” @EnableWebMvcSecurity或在其中注册此Bean,mvc:argument-resolvers这与我在上面的Spring 3.1解决方案中描述的方式相同。
(org.springframework.security.web.method.annotation.)AuthenticationPrincipalArgumentResolver
@EnableWebMvcSecurit
mvc:argument-resolvers
<mvc:annotation-driven> <mvc:argument-resolvers> <bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" /> </mvc:argument-resolvers> </mvc:annotation-driven>