Principal以UsernamePasswordAuthenticationToken的形式返回

时间:2017-04-16 23:02:58

标签: spring-boot spring-security

我遇到了我认为可能是个错误的内容。

我使用Spring Boot和Spring Security。 Normaly一切运行良好但是当我尝试通过HttpServletRequest或直接从控制器获取主体时,由于一些奇怪的原因它被转换为UsernamePasswordAuthenticationToken。当我使用SecurityContextHolder.getContext().getAuthentication().getPrincipal()时,它返回正确的对象。

请参阅下面的代码,请参阅最近6行中的评论,了解实际返回的内容。

@RequestMapping(method = RequestMethod.POST)
public ElementDto postElement(@RequestBody @Valid ElementDto element, BindingResult bindingResult, HttpServletRequest httpServletRequest, Principal principal) {
    logger.info("postElement - {}", element);
    if (bindingResult.hasErrors()) {
        throw new SpringBootCommonError(bindingResult.getAllErrors().get(0).getDefaultMessage(), SpringBootCommonErrorEnum.VALIDATION);
    }
    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = (UsernamePasswordAuthenticationToken)principal; /*is of type UsernamePasswordAuthenticationToken*/
    Principal requestPrincipal = httpServletRequest.getUserPrincipal();/*is of type UsernamePasswordAuthenticationToken*/
    Principal principalFromCast = (Principal)usernamePasswordAuthenticationToken.getPrincipal();/*is of type User (what I want)*/
    Object securityPrincipal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();/*is of type (what I want)*/
    element.setUploadedBy(((User) httpServletRequest.getUserPrincipal()).getEntityNo());
    return elementService.createElement(element);
}

2 个答案:

答案 0 :(得分:2)

UsernamePasswordAuthenticationToken 是界面 Authentication 的实现,它扩展了界面PrincipalPrincipal在JSE java.security中定义。 UsernamePasswordAuthenticationToken是Spring Security中的一个概念,它实现了Principal接口。

UsernamePasswordAuthenticationToken基本上是校长。

    /**
     * The identity of the principal being authenticated. In the case of an authentication
     * request with username and password, this would be the username. Callers are
     * expected to populate the principal for an authentication request.
     * <p>
     * The <tt>AuthenticationManager</tt> implementation will often return an
     * <tt>Authentication</tt> containing richer information as the principal for use by
     * the application. Many of the authentication providers will create a
     * {@code UserDetails} object as the principal.
     *
     * @return the <code>Principal</code> being authenticated or the authenticated
     * principal after authentication.
     */
    Object getPrincipal();

这是getPrincipal()

SecurityContextHolder.getContext().getAuthentication().getPrincipal();方法的javadoc

所以我会假设你真正想要的是 UserDetails 而不是校长。

答案 1 :(得分:-1)

如果您尚未明确配置,那么您希望如何对用户进行身份验证,Spring Security默认使用

DaoAuthenticationProvider

用于使用

的身份验证
UsernamePasswordAuthenticationToken 

用于验证您的用户,如果您使用用户名和密码来验证您的用户。

这就是为什么,当你想要获得

Principal object

你需要明确地对

进行类型转换
UsernamePasswordAuthenticationToken    

注意:Spring Security也提供了许多其他身份验证机制,例如X.509,LDAP,甚至您也可以使用JDBC身份验证。