0

私はspring-boot-starter-securityを使用しています。 WebSecurityConfigationDaoAuthenticationProviderプロバイダを、BCryptPasswordEncoderに認証を設定しました。また、UserDetailsServiceの実装では、実際のハッシュに設定されたpasswordフィールドを持つUserオブジェクトが返されます。Java Spring Securityのパスワードハッシュで認証できる理由

正常に動作しているようです。しかし私は、パスワードまたはハッシュのいずれかで正常に認証できることに気づいた。

たとえば、パスワード自体は、生成されたUUID 51a80a6a-8618-4583-98d2-d77d103a62c6で、$2a$10$u4OSZf7B9yJvQ5UYNNpy7O4f3g0gfUMl2Xmm3h282W.3emSN3WqxOにエンコードされています。

完全なWebセキュリティの設定:

@Configuration 
@EnableWebSecurity 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private DemoUserDetailsService userDetailsService; 

    @Autowired 
    private DaoAuthenticationProvider authenticationProvider; 

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.authenticationProvider(authenticationProvider); 
     auth.userDetailsService(userDetailsService); 
     auth.inMemoryAuthentication().withUser("user").password("password").roles("SUPER", "BASIC"); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.authorizeRequests().antMatchers("/**").hasRole("BASIC").and().httpBasic(); 
     http.csrf().disable(); 
    } 
} 

@Service 
public class DemoUserDetailsService implements UserDetailsService { 

    @Autowired 
    private UserRepository userRepository; 

    @Override 
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { 
     UserDAO userDAO = userRepository.findByEmailAndActivated(email); 
     if (userDAO == null) { 
      throw new UsernameNotFoundException(String.format("Email %s not found", email)); 
     } 
     return new User(email, userDAO.getPasswordHash(), getGrantedAuthorities(email)); 
    } 

    private Collection<? extends GrantedAuthority> getGrantedAuthorities(String email) { 
     return asList(() -> "ROLE_BASIC"); 
    } 
} 

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

@Bean 
public DaoAuthenticationProvider authenticationProvider() { 
    DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); 
    authenticationProvider.setUserDetailsService(userDetailsService); 
    authenticationProvider.setPasswordEncoder(passwordEncoder); 
    return authenticationProvider; 
} 

は、なぜ私は両方の文字列を使用して認証することができていますか?間違ったことをやっているのですか?私はドキュメントで何かを見つけることができませんでした。

+0

オッズは何ですか。ただし、エンコードされた文字列をエンコードすることでチェックしてください。これは同じ出力になる可能性があります(私はそれを本当に疑っています)。結果のハッシュは一意ではないので、これは可能ですが、可能性は低いですが、 – AxelH

+0

が設定を表示するため、私はbcryptでセキュリティを実装しています。 –

+0

@shutdown -hあなたはどのような構成を正確に意味していますか? – Tom

答えて

1

DaoAuthenticationProvider

protected void additionalAuthenticationChecks(UserDetails userDetails, 
      UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { 
     Object salt = null; 

     if (this.saltSource != null) { 
      salt = this.saltSource.getSalt(userDetails); 
     } 

     if (authentication.getCredentials() == null) { 
      logger.debug("Authentication failed: no credentials provided"); 

      throw new BadCredentialsException(messages.getMessage(
        "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), userDetails); 
     } 

     String presentedPassword = authentication.getCredentials().toString(); 

     if (!passwordEncoder.isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) { 
      logger.debug("Authentication failed: password does not match stored value"); 

      throw new BadCredentialsException(messages.getMessage(
        "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), userDetails); 
     } 
    } 

このデリゲートのadditionalAuthenticationChecks方法でありますs。 1つは明示的に、あなたが設定し、1つは暗黙的に、auth.userDetailsService(userDetailsService);を呼び出すときにはフードの下で設定され、この暗黙のプロバイダの場合はパスワードエンコーダを設定しません。

これを試してみてください:

@Override 
protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
    auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder()); 
    auth.inMemoryAuthentication().withUser("user").password("password").roles("SUPER", "BASIC"); 
} 

そして、あなたの手で構成されたプロバイダを削除するには - あなたが実際にそれを必要といけないしているようです。

希望します。

+0

実際にあなたは正しいです。追加(userDetailsS​​ervice).passwordEncoder(新しいBCryptPasswordEncoder());助けてくれた。 – Tom

-1

ベスト・アプローチは、デバッガーを接続することです。パスワードを一致させるためPasswordEncoderを使用しての実際のロジックは、私はあなたの設定に応じて、あなたは、実際には2つのDaoAuthenticationProviderを取得しているので、このことが起こると思いBCryptPasswordEncoder

public boolean matches(CharSequence rawPassword, String encodedPassword) { 
     if (encodedPassword == null || encodedPassword.length() == 0) { 
      logger.warn("Empty encoded password"); 
      return false; 
     } 
    if (!BCRYPT_PATTERN.matcher(encodedPassword).matches()) { 
     logger.warn("Encoded password does not look like BCrypt"); 
     return false; 
    } 

    return BCrypt.checkpw(rawPassword.toString(), encodedPassword); 
} 
+1

ありがとうございますが、これは答えではありません。 – Tom

関連する問題