Spring Security Ouath2:Principal对象不返回扩展的UserDetails

Rob*_*ans 10 spring spring-security spring-security-oauth2

上周,我开始扩展UserDetails类,以便能够支持自定义字段.关于这个领域的特殊之处在于它填充了一个取决于请求参数的值.我设法正确地实现了这个(所以问题不关注那个).

现在的问题是,在成功登录后,UserDetails对象被正确填充(我能够使用AuthenticationSuccessHandler看到这一点),并且客户端从OAuth2提供程序接收JWT令牌.然后,客户端通过访问"/ uaa/user"端点尝试获取有关用户的更多详细信息.这被设置为返回Principal对象.但在检查Principal对象的内容后,我被告知UserDetails对象丢失了.方法getPrincipal()仅返回用户名而不是UserDetails对象.

根据这个问题,这是登录失败的结果.AuthenticationToken(在本例中为UsernamePasswordAuthenticationToken)被AuthenticationManager拒绝.我不知道它为什么要做这样的事情.使用默认UserDetails对象的身份验证似乎工作得很好.有人可以帮我解决这个问题吗?

有关已实现类的一些细节(如上所述).有些代码因此被遗漏.

CustomUserDetails

public class CustomUserDetails extends User {

  private final Integer custom;

  public CustomUserDetails (...default params..., Integer custom) {
    super(...default params...);
    this.custom = custom;
  }
}
Run Code Online (Sandbox Code Playgroud)

CustomUserDetailsS​​ervice

@Service
public class CustomUserDetailsService implements UserDetailsService {
  @Override
  public CustomUserDetails loadUserByUsername(String username) throw UsernameNotFoundException {
    return new CustomUserDetails(...default params..., 12345);
  }
}
Run Code Online (Sandbox Code Playgroud)

组态

@Autowired
private CustomUserDetails userDetails;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  auth.userDetailsService(userDetails);
}
Run Code Online (Sandbox Code Playgroud)

用户端点

@RequestMapping(value = "/user", method = RequestMethod.GET)
@ResponseBody
public Principal getDetails(Principal user) {
  return user;
}
Run Code Online (Sandbox Code Playgroud)

这里返回的Principal对象应该包含UserDetails对象,并且应该将它返回给客户端.但是,当你调用getPrincipal()时,它只返回一个带有用户名的String;

最后,我希望User端点返回的JSON(返回Principle对象)包含我添加到UserDetails的自定义字段.

提前致谢.

Jai*_*o99 6

通常,您需要注释@AuthenticationPrincipal,但我建议您构建自己的注释,如下所示:

/**
 * Our own {@link AuthenticationPrincipal} annotation as suggested by
 * http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#mvc-authentication-principal
 *
 */
@Target({ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@AuthenticationPrincipal
public @interface CurrentUser {}
Run Code Online (Sandbox Code Playgroud)

然后你可以Principal用这种方式:

@RequestMapping(..)
public Principal test(@CurrentUser Principal principal){..}
Run Code Online (Sandbox Code Playgroud)

但是,恕我直言,你应该拥有自己的校长Impl,或者更确切地说扩展现有的impl.这样的事情:

public MyPrincipal extends org.springframework.security.core.userdetails.User {..}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可以随意返回值.