前言:自从Spring-Security 3.2以来,在这个答案的末尾描述了一个很好的注释@AuthenticationPrincipal。这是使用Spring-Security> = 3.2时最好的方法。
当你:
>使用旧版本的Spring-Security,
>需要通过存储在principal或中的一些信息(如登录名或ID)从数据库加载您的自定义用户对象
>想要了解一个HandlerMethodArgumentResolver或WebArgumentResolver如何以优雅的方式解决这个问题,或者只是想了解背后的背景@AuthenticationPrincipal和AuthenticationPrincipalArgumentResolver(因为它是基于一个HandlerMethodArgumentResolver)
然后继续阅读 – 否则只是使用@AuthenticationPrincipal并感谢Rob Winch(@AuthenticationPrincipal的作者)和Lukas Schmelzeisen(为他的答案)。
(BTW:我的答案有点老(2012年1月),所以它是Lukas Schmelzeisen,作为第一个与基于Spring Security 3.2的@AuthenticationPrincipal注释解决方案)。
然后你可以在你的控制器中使用
public ModelAndView someRequestHandler(Principal principal) {
User activeUser = (User) ((Authentication) principal).getPrincipal();
...
}
这是确定如果你需要它一次。但是如果你需要它的几倍它的丑陋,因为它污染了你的控制器的基础设施细节,通常应该被框架隐藏。
所以你真正想要的是有一个这样的控制器:
public ModelAndView someRequestHandler(@ActiveUser User activeUser) {
...
}
Object resolveArgument(MethodParameter methodParameter,
NativeWebRequest webRequest)
throws Exception
获得Web请求(第二个参数),并且必须返回用户,如果它感觉负责方法参数(第一个参数)。
自从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 {}
在配置中,您只需要添加:
id="applicationConversionService">
应该注意,如果你使用Spring 3.1,他们推荐通过WebArgumentResolver的HandlerMethodArgumentResolver。 – 见Jay的评论
与Spring 3.1的HandlerMethodArgumentResolver相同
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;
}
}
}
在配置中,您需要添加此
Spring-Security 3.2解决方案
Spring Security 3.2(不要与Spring 3.2混淆)在解决方案中有一个自己的构建:@AuthenticationPrincipal.这在Lukas Schmelzeisen`s answer中很好地描述
它只是写作
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
...
}
为了得到这个工作,你需要注册AuthenticationPrincipalArgumentResolver:通过“activate”@EnableWebMvcSecurity或者注册mvc:argument-resolvers中的这个bean – 就像我上面描述的Spring 3.1解决方案一样。