2017-04-16 128 views
0

我正在體驗我認爲可能是一個錯誤。委託人返回爲UsernamePasswordAuthenticationToken

我正在使用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); 
} 

回答

2

UsernamePasswordAuthenticationToken是接口Authentication它擴展了界面Principal的實現。在JSE java.security中定義了PrincipalUsernamePasswordAuthenticationToken是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(); 

這是SecurityContextHolder.getContext().getAuthentication().getPrincipal();

getPrincipal()方法的Javadoc所以我會假設你真正想要的是一個UserDetails沒有一個主體。

+0

我明白UsernamePasswordAuthenticationToken我的問題是,爲什麼是我的校長被返回UsernamePasswordAuthenticationToken例如下面的代碼工作 '((用戶)((UsernamePasswordAuthenticationToken)本金).getPrincipal())。getEntityNo()'但是這個代碼不不是'((用戶)主體).getEntityNo()' 我不認爲我應該把它轉換成UsernamePasswordAuthenticationToken,然後返回到本金,如果它最初是主體 –

+1

它不是很清楚,你指的是什麼'委託人'在你的評論。這取決於身份驗證提供程序如何實現它。 HttpServeletRequest和SecurityContext都會返回你正確的主體,即UsernamePasswordAuthenticationToken – Simon

-1

如果您還沒有明確的配置,你想怎樣,然後驗證您的用戶使用,Spring Security默認使用

DaoAuthenticationProvider 

針對使用

UsernamePasswordAuthenticationToken 

用於驗證用戶,如果認證正在使用用戶名和密碼來驗證您的用戶。

這就是爲什麼,當你試圖讓

Principal object 

你需要明確強制轉換爲

UsernamePasswordAuthenticationToken  

注意的原因:Spring Security提供許多其他的認證機制以及,說X .509,LDAP,甚至您也可以使用JDBC身份驗證。