主体作为 UsernamePasswordAuthenticationToken 返回

Lwa*_*ent 3 spring-security spring-boot

我遇到了我认为可能是错误的情况。

我正在使用 Spring Boot 和 Spring Security。通常情况下,一切都运行良好,但是当我尝试通过控制器或直接从控制器获取主体时,由于某种奇怪的原因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);
}
Run Code Online (Sandbox Code Playgroud)

小智 5

UsernamePasswordAuthenticationToken是接口的实现Authentication,它扩展了接口PrincipalPrincipal在 JSE 中定义java.securityUsernamePasswordAuthenticationToken是 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();
Run Code Online (Sandbox Code Playgroud)

getPrincipal()这是该方法的 javadocSecurityContextHolder.getContext().getAuthentication().getPrincipal();

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