序言:从Spring-Security 3.2开始,在这个答案的末尾描述了一个很好的注释。这是使用Spring-Security >= 3.2时的最佳方法。@AuthenticationPrincipal
当您:
- 使用旧版本的Spring-Security,
- 需要通过存储在主体中的一些信息(如登录名或 id)从数据库中加载自定义用户对象,或者
- 想学习如何以一种优雅的方式解决这个问题,或者只是想学习一个背后的背景和(因为它是基于一个
HandlerMethodArgumentResolver
WebArgumentResolver
@AuthenticationPrincipal
AuthenticationPrincipalArgumentResolver
HandlerMethodArgumentResolver
)
然后继续阅读 - 否则只需使用并感谢Rob Winch(作者)和Lukas Schmelzeisen(他的答案)。@AuthenticationPrincipal
@AuthenticationPrincipal
(顺便说一句:我的答案有点旧(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) {
...
}
因此,您只需要实现WebArgumentResolver
。它有一个方法
Object resolveArgument(MethodParameter methodParameter,
NativeWebRequest webRequest)
throws Exception
它获取 Web 请求(第二个参数),并且必须返回 if 它感觉对方法参数(第一个参数)负责。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>
@See:学习自定义 Spring MVC @Controller方法参数
应该注意的是,如果您使用的是Spring 3.1,他们建议使用HandlerMethodArgumentResolver而不是WebArgumentResolver。- 见杰伊的评论
与HererMethodArgumentResolver
for 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;
}
}
}
在配置中,您需要添加此
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="CurrentUserHandlerMethodArgumentResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>
@See 利用 Spring MVC 3.1 HandlerMethodArgumentResolver 接口
弹簧-安全3.2解决方案
Spring Security 3.2(不要与Spring 3.2混淆)有自己的内置解决方案:@AuthenticationPrincipal
()。这在Lukas Schmelzeisen的回答中得到了很好的描述。org.springframework.security.web.bind.annotation.AuthenticationPrincipal
它只是写作
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
...
}
要使这项工作正常工作,您需要注册():通过“激活”或通过注册此bean - 就像我在上面的may Spring 3.1解决方案中描述的那样。AuthenticationPrincipalArgumentResolver
org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver
@EnableWebMvcSecurity
mvc:argument-resolvers
@See Spring Security 3.2 参考,第 11.2 章,@AuthenticationPrincipal
弹簧-安防4.0解决方案
它的工作方式类似于Spring 3.2解决方案,但在Spring 4.0中,和被“移动”到另一个包中:@AuthenticationPrincipal
AuthenticationPrincipalArgumentResolver
(但是旧包装中的旧类仍然存在,所以不要混合它们!
它只是写作
import org.springframework.security.core.annotation.AuthenticationPrincipal;
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
...
}
要使这项工作正常工作,您需要注册():通过“激活”或通过注册此bean - 就像我在上面的may Spring 3.1解决方案中描述的那样。org.springframework.security.web.method.annotation.
AuthenticationPrincipalArgumentResolver
@EnableWebMvcSecurity
mvc:argument-resolvers
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
@See Spring Security 5.0 参考,第 39.3 章 @AuthenticationPrincipal