如何获取活动用户的UserDetails

铁皮熊:

在我的控制器中,当我需要活动(登录)用户时,我正在执行以下操作以获取UserDetails实现:

User activeUser = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
log.debug(activeUser.getSomeCustomField());

它工作正常,但我认为Spring在这种情况下可以使生活更轻松。有没有办法将UserDetails自动接线连接到控制器或方法中?

例如,类似:

public ModelAndView someRequestHandler(Principal principal) { ... }

但是UsernamePasswordAuthenticationToken我得到了,UserDetails而不是得到了

我正在寻找一种优雅的解决方案。有任何想法吗?

拉尔夫:

序言:从Spring-Security 3.2开始@AuthenticationPrincipal,此答案的末尾描述了一个不错的注释当您使用Spring-Security> = 3.2时,这是最好的方法。

当你:

  • 使用较旧版本的Spring-Security,
  • 需要通过存储在主体中的某些信息(例如登录名或ID)从数据库加载您的自定义用户对象,
  • 想要了解a HandlerMethodArgumentResolver如何WebArgumentResolver以一种优雅的方式解决此问题,或者只是想要了解@AuthenticationPrincipaland 的背景AuthenticationPrincipalArgumentResolver(因为它基于HandlerMethodArgumentResolver

然后继续阅读-否则,请使用@AuthenticationPrincipal并感谢Rob Winch(的作者@AuthenticationPrincipal)和Lukas Schmelzeisen(的回答)。

(顺便说一句:我的回答有点老(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>

@See:学习自定义Spring MVC @Controller方法参数

应该注意的是,如果您使用的是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>

@See 利用Spring MVC 3.1 HandlerMethodArgumentResolver接口


Spring-Security 3.2解决方案

春季安全3.2(不使用Spring 3.2混淆)在溶液中有自己的编译:@AuthenticationPrincipalorg.springframework.security.web.bind.annotation.AuthenticationPrincipal)。Lukas Schmelzeisen的回答对此进行了很好的描述。

只是在写

ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
    ...
 }

要使此工作正常进行,您需要注册AuthenticationPrincipalArgumentResolverorg.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver):通过“激活” @EnableWebMvcSecurity或在其中注册此Bean,mvc:argument-resolvers这与我在上面的Spring 3.1解决方案中描述的方式相同。

@请参阅《Spring Security 3.2参考》的第11.2章。@AuthenticationPrincipal


Spring-Security 4.0解决方案

它的工作方式类似于Spring 3.2解决方案,但在Spring 4.0中,@AuthenticationPrincipalAuthenticationPrincipalArgumentResolver被“移动”到另一个软件包中:

(但是旧包中的旧类仍然存在,因此请不要混合使用!)

只是在写

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解决方案中描述的方式相同。

<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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何使用“查询用户”获取活动用户名

使用gitlab api,如何获取活动用户列表?

如何获取tomcat中的活动用户列表

如何在Google Apps脚本自定义功能中获取“活动用户”的用户属性

如何通过安装onEdit触发器获取活动用户电子邮件?

如何从应用制作工具中的活动用户会话中获取 Google UserId?

如何在使用C ++的SYSTEM进程中获取活动用户名?

获取WooCommerce会员计划的所有活动用户

无法获取活动用户的电子邮件

使用 shell 脚本在 Windows 上获取活动用户的警告

如何将活动用户传递给Django ModelForms

如何在Laravel 5.2中登录活动用户?

如何创建在线/活动用户列表?

SQL:如何根据参数显示/隐藏非活动用户

活动用户数

获取总用户列表以及在OR条件下匹配的mongodb中的活动用户

如何在odoo 9中存储当前记录的用户ID或活动用户ID?

FB Analytics如何基于IP或注册用户捕获活动用户

MongoDB聚合/组->按日期获取单个活动用户的数量

Lightdm活动用户指示已删除

强制非活动用户注销

Firebase报告太多活动用户

非活动用户的SQL查询

禁用Active Directory非活动用户

如何禁用Windows 8.1中最后一个活动用户的自动登录?

如何启动用户仅在android中输入一次信息的活动?

如何自动从数据库和身份验证中删除Firebase非活动用户?

如何在ModelBackEnd中检查Django中的非活动用户

如何在下拉菜单中仅列出活动用户