如何获取活动用户的UserDetails [英] How to get active user's UserDetails

查看:298
本文介绍了如何获取活动用户的UserDetails的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In my controllers, when I need the active (logged in) user, I am doing the following to get my UserDetails implementation:

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

它工作正常,但我认为Spring可以在这样的情况下让生活更轻松。有没有办法让 UserDetails 自动装入控制器或方法?

It works fine, but I would think Spring could make life easier in a case like this. Is there a way to have the UserDetails autowired into either the controller or the method?

例如,像:

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

但是我没有得到 UsernamePasswordAuthenticationToken ,而是获得 UserDetails 相反?

But instead of getting the UsernamePasswordAuthenticationToken, I get a UserDetails instead?

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

I'm looking for an elegant solution. Any ideas?

推荐答案

序言:自Spring-Security 3.2以来,有一个很好的注释 @AuthenticationPrincipal 在本答案结尾处描述。当你使用Spring-Security> = 3.2时,这是最好的方法。

Preamble: Since Spring-Security 3.2 there is a nice annotation @AuthenticationPrincipal described at the end of this answer. This is the best way to go when you use Spring-Security >= 3.2.

当你:


  • 使用旧版本的Spring-Security,

  • 需要通过存储在数据库中的一些信息(如登录名或ID)从数据库加载自定义用户对象校长或

  • 想了解 HandlerMethodArgumentResolver WebArgumentResolver 如何解决这个问题以优雅的方式,或者只是想了解 @AuthenticationPrincipal AuthenticationPrincipalArgumentResolver 背后的背景(因为它基于a HandlerMethodArgumentResolver

  • use an older version of Spring-Security,
  • need to load your custom User Object from the Database by some information (like the login or id) stored in the principal or
  • want to learn how a HandlerMethodArgumentResolver or WebArgumentResolver can solve this in an elegant way, or just want to an learn the background behind @AuthenticationPrincipal and AuthenticationPrincipalArgumentResolver (because it is based on a HandlerMethodArgumentResolver)

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

then keep on reading — else just use @AuthenticationPrincipal and thank to Rob Winch (Author of @AuthenticationPrincipal) and Lukas Schmelzeisen (for his answer).

(顺便说一句:我的回答有点老了(1月) 2012),所以 Lukas Schmelzeisen 作为第一个出现在 @AuthenticationPrincipal 基于Spring Security 3.2的注释解决方案。)

(BTW: My answer is a bit older (January 2012), so it was Lukas Schmelzeisen that come up as the first one with the @AuthenticationPrincipal annotation solution base on Spring Security 3.2.)

然后你可以使用你的控制器

Then you can use in your controller

public ModelAndView someRequestHandler(Principal principal) {
   User activeUser = (User) ((Authentication) principal).getPrincipal();
   ...
}






如果你需要一次就可以了。但是如果你需要它几次丑陋,因为它会污染你的控制器的基础设施细节,通常应该被框架隐藏。


That is ok if you need it once. But if you need it several times its ugly because it pollutes your controller with infrastructure details, that normally should be hidden by the framework.

所以你真正想要的是有一个像这样的控制器:

So what you may really want is to have a controller like this:

public ModelAndView someRequestHandler(@ActiveUser User activeUser) {
   ...
}

因此你只需要实现一个 WebArgumentResolver 。它有一个方法

Therefore you only need to implement a WebArgumentResolver. It has a method

Object resolveArgument(MethodParameter methodParameter,
                   NativeWebRequest webRequest)
                   throws Exception

获取Web请求(第二个参数)并且必须返回用户如果它感觉负责方法参数(第一个参数)。

That gets the web request (second parameter) and must return the User if its feels responsible for the method argument (the first parameter).

从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实例都应该从安全上下文中获取,但是永远不是命令对象,则可以跳过它。

You need to define the Custom Annotation -- You can skip it if every instance of User should always be taken from the security context, but is never a command object.

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ActiveUser {}

在配置中你只需要添加:

In the configuration you only need to add this:

<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,他们会在WebArgumentResolver上推荐HandlerMethodArgumentResolver。 - 查看Jay的评论

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;
          }
     }
}

在配置中,您需要添加此

In the configuration, you need to add this

<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(不要与Spring 3.2混淆)有自己的内置版本解决方案: @AuthenticationPrincipal org.springframework.security.web.bind.annotation.AuthenticationPrincipal )。这在 Lukas Schmelzeisen的回答中有详细描述。

Spring Security 3.2 (do not confuse with Spring 3.2) has own build in solution: @AuthenticationPrincipal (org.springframework.security.web.bind.annotation.AuthenticationPrincipal) . This is nicely described in Lukas Schmelzeisen`s answer

它只是写作

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

要实现此功能,您需要注册 AuthenticationPrincipalArgumentResolver org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver ):通过激活 @EnableWebMvcSecurity 或通过在 mvc:argument-resolvers 中注册这个bean - 就像我在上面提到的Spring 3.1解决方案一样。

To get this working you need to register the AuthenticationPrincipalArgumentResolver (org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver) : either by "activating" @EnableWebMvcSecurity or by registering this bean within mvc:argument-resolvers - the same way I described it with may Spring 3.1 solution above.

@参见 Spring Security 3.2参考,第11.2章。 @AuthenticationPrincipal

它与Spring 3.2解决方案类似,但在Spring 4.0中 @AuthenticationPrincipal AuthenticationPrincipalArgumentResolver 被移动到另一个包裹:

It works like the Spring 3.2 solution, but in Spring 4.0 the @AuthenticationPrincipal and AuthenticationPrincipalArgumentResolver was "moved" to an other package:

  • org.springframework.security.core.annotation.AuthenticationPrincipal
  • org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver

(但旧包中的旧类仍然存在,所以不要混合它们!)

(But the old classes in its old packges still exists, so do not mix them!)

这只是写作

import org.springframework.security.core.annotation.AuthenticationPrincipal;
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
    ...
}

要使其正常工作,您需要注册( org.springframework.security.web.method.annotation。 AuthenticationPrincipalArgumentResolver :通过激活 @EnableWebMvcSecurity 或者在 mvc:argument-resolvers 中注册此bean - 就像我在上面描述的Spring Spring 3.1解决方案一样。

To get this working you need to register the (org.springframework.security.web.method.annotation.) AuthenticationPrincipalArgumentResolver : either by "activating" @EnableWebMvcSecurity or by registering this bean within mvc:argument-resolvers - the same way I described it with may Spring 3.1 solution above.

<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

这篇关于如何获取活动用户的UserDetails的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆