2017-05-05 42 views
1

我在spring引導中實現了OAuth 2.0。當用戶傳遞他的用戶名/密碼時,spring會嘗試通過散列密碼並將其與已通過散列的密碼進行比較來驗證密碼。但是,Spring總是漏掉鹽,所以它總是返回錯誤的憑據。我怎樣才能把鹽傳給春天?

我該如何將鹽通過泉水?

這裏是我的UserDAO類:

@Service 
public class UserDAO implements UserDetailsService, SaltSource{ 

private LoginDetails user; 
private UserDetailsImpl userDetailsImpl; 

@Autowired 
private LoginDetailsManager loginDetailsManager; 

@Override 
public UserDetails1 loadUserByUsername(String username) throws UsernameNotFoundException { 

    System.out.println("Get user"); 
    user = loginDetailsManager.getByUsername(username); 
    System.out.println(user.toString()); 
    if (user == null) { 
     throw new UsernameNotFoundException(
       "User " + username + " not found."); 
    } 

    GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_USER"); 
    List<GrantedAuthority> grantedAuthorities = new ArrayList<>(); 
    grantedAuthorities.add(grantedAuthority); 

    String password = user.getPasswordHash(); 
    String salt = user.getSalt(); 
    userDetailsImpl = new UserDetailsImpl(user.getUsername(), user.getPasswordHash(), salt, grantedAuthorities); 

    return new UserDetailsImpl(
      user.getUsername(), 
      user.getPasswordHash(), 
      salt, 
      grantedAuthorities); 
} 
} 

以下是我的AuthorizationServer類:

@Configuration 
@EnableAuthorizationServer 
protected class AuthorizationApplication extends AuthorizationServerConfigurerAdapter { 

    @Bean 
    public PasswordEncoder passwordEncoder() { 
     return new StandardPasswordEncoder(); 
    } 

    @Autowired 
    private PasswordEncoder passwordEncoder; 

    @Autowired 
    private AuthenticationManager authenticationManager; 


    @Bean 
    protected AuthorizationCodeServices getAuthorizationCodeServices() { 
     return new JdbcAuthorizationCodeServices(dataSource); 
    } 


    @Override 
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 
     clients.jdbc(dataSource); 
    } 


    @Override 
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 
     AuthorizationCodeServices services = getAuthorizationCodeServices(); 
     JdbcTokenStore tokenStore = getTokenStore(); 
     endpoints 
       .userDetailsService(userDetailsService) 
       .authorizationCodeServices(services) 
       .authenticationManager(authenticationManager) 
       .tokenStore(tokenStore) 
       .approvalStoreDisabled(); 
    } 

    @Override 
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { 
     security.allowFormAuthenticationForClients(); 
     security.passwordEncoder(passwordEncoder); 
    } 

從一個小的調試,我發現,從春季SaltSource(org.springframework得到它的鹽。 security.authentication.dao.SaltSource)。我無法弄清楚如何配置該來源。

+0

因爲我在我的數據庫中有SHA256(hash + password) - 我從UserDAO類返回到Spring,作爲UserDetailsImpl對象的屬性'user.getPasswordHash()'。春天將它與SHA256(密碼)進行比較,我被授權。 –

+0

對不起,我不明白。目前,我有一個手動填充的數據庫進行測試。春天沒有鹽會怎麼認證? –

+0

好的,請耐心等待。爲了避免複雜性,我創建了一個實現PasswordEncoder的新類(使用兩種方法 - 編碼簡單的sha256哈希和matches()),並開始使用它來代替StandardPasswordEncoder。有沒有一種方法可以爲此配置SaltSource? –

回答

1

無法找出一種方法,因此實現自己PasswordEncoder和使用一個靜態變量從UserDAO傳遞鹽:

public class PasswordEncoderImpl implements PasswordEncoder { 

    public static Constants constants = new Constants(); 

    @Override 
    public String encode(CharSequence rawPassword) { 
     return DigestUtils.sha256Hex(rawPassword.toString()); 
    } 

    @Override 
    public boolean matches(CharSequence rawPassword, String encodedPassword) { 
     String salt = constants.getSalt(); 

/** 
* If salt is null, it means the value in constants object is empty now. 
* => client-secret validation is going on 
* => we just need the comparision of plain-text string. 
*/ 
     if(salt != null) { 
// case of password authentication 
      return DigestUtils.sha256Hex(salt + rawPassword).equalsIgnoreCase(encodedPassword); 
     } else { 
    //case of client-secret authentication 
     return rawPassword.equals(encodedPassword); 
     } 
    } 
} 

設置常數的值對象在loadUserByUsername方法。