Spring Boot BCryptPasswordEncoder 编码密码看起来不像 BCrypt

Posted

技术标签:

【中文标题】Spring Boot BCryptPasswordEncoder 编码密码看起来不像 BCrypt【英文标题】:Spring Boot BCryptPasswordEncoder Encoded password does not look like BCrypt 【发布时间】:2018-10-09 03:02:20 【问题描述】:

我正在使用 OAuth2 和 JPA 编写 Spring Boot REST 安全 API。在访问访问令牌时,我收到警告,因为编码密码看起来不像 BCrypt。 当我点击邮递员的网址时 http://localhost:8080/oauth/token?grant_type=password&username=user&password=user 我明白了

WARN 26648 --- [nio-8080-exec-2] o.s.s.c.bcrypt.BCryptPasswordEncoder     : Encoded password does not look like BCrypt

在邮递员中,基本身份验证结果返回为 401


    "timestamp": "2018-04-28T12:05:53.462+0000",
    "status": 401,
    "error": "Unauthorized",
    "message": "Unauthorized",
    "path": "/oauth/token"

我已定义的 Bean 和存储库。 我使用了 secret("bcrypt 和 secret("noop),但都没有帮助。对此的任何帮助将不胜感激。 以下是申请详情

授权服务器

@Configuration
@EnableAuthorizationServer

public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter 

    @Autowired
    private AuthenticationManager authenticationManager;

@Autowired
private PasswordEncoder passwordEncoder;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception 
        // TODO Auto-generated method stub
        endpoints.authenticationManager(authenticationManager);
         //.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);;
    

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception 
        // TODO Auto-generated method stub
        security.checkTokenAccess("isAuthenticated()");
    

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception 
        // TODO Auto-generated method stub


        clients.inMemory().withClient("my-trusted-client")
        .authorizedGrantTypes("client_credentials", "password")
        .authorities("ROLE_CLIENT","ROLE_TRUSTED_CLIENT").scopes("read","write","trust")
        .resourceIds("oauth2-resource").accessTokenValiditySeconds(5000).secret("bcryptsecret");
    


资源服务器

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter 

    @Override
    public void configure(HttpSecurity http) throws Exception 

        http.headers().frameOptions().disable().and()
        .authorizeRequests()
        .antMatchers("/","/home","/register","/login").permitAll()
        .antMatchers("/asd/**").authenticated();
    


服务

@Service
public class UserService extends WebSecurityConfigurerAdapter 
     @Autowired
        private UserRepository repo;

     @Autowired
     private BCryptPasswordEncoder  passwordEncoder;


     public void save(User user)
          // user.setPassword(getPasswordEncoder().encode(user.getPassword()));
         user.setPassword(passwordEncoder.encode(user.getPassword()));
         // user.setPassword(user.getPassword());
         repo.save(user);
        


     @Bean
        @Override
        public AuthenticationManager authenticationManager() throws Exception 

            return super.authenticationManager();
        

我的自定义用户详情

public class CustomUserDetails implements UserDetails 

    private String username;
    private String password;
    Collection <? extends GrantedAuthority> authorities;

    public CustomUserDetails(User username) 
        this.username= username.getUsername();
        this.password=username.getPassword();
         this.authorities = translate(username.getRoles());

    

    private Collection<? extends GrantedAuthority> translate(List<Role> roles) 
        List<GrantedAuthority> authorities = new ArrayList<>();
        for (Role role : roles) 
            String name = role.getName().toUpperCase();
            //Make sure that all roles start with "ROLE_"
            if (!name.startsWith("ROLE_"))
                name = "ROLE_" + name;
            authorities.add(new SimpleGrantedAuthority(name));
        
        return authorities;
    


    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() 
        // TODO Auto-generated method stub
        return authorities;
    

    @Override
    public String getPassword() 
        // TODO Auto-generated method stub
        return password;
    

    @Override
    public String getUsername() 
        // TODO Auto-generated method stub
        return username;
    

    @Override
    public boolean isAccountNonExpired() 
        // TODO Auto-generated method stub
        return true;
    

主类

@ComponentScan
@SpringBootApplication
@Configuration
@EnableWebSecurity
public class SpringBootOauth2Application 

    /*@Autowired
    private PasswordEncoder passwordEncoder;
    */
    public static void main(String[] args) 
        SpringApplication.run(SpringBootOauth2Application.class, args);
    


    @Bean
    public BCryptPasswordEncoder  getPasswordEncoder() 
       return new BCryptPasswordEncoder();

 

    @Autowired
    public void authenticationManager(AuthenticationManagerBuilder builder, UserRepository user, UserService service) throws Exception
    
        if(user.count()==0)
            service.save(new User("user","user", Arrays.asList(new Role("USER"), new Role("ACTUATOR"))));

        builder.userDetailsService(userDetailsService(user)).passwordEncoder(getPasswordEncoder());
    
    private UserDetailsService userDetailsService(final UserRepository repository) 
        return username -> new CustomUserDetails(repository.findByUsername(username));
    


application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/db1
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.security.oauth2.resource.filter-order=3

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl


spring.jpa.hibernate.ddl-auto=create-drop

spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect


 spring.jpa.properties.hibernate.hbm2ddl.auto = update

spring.jpa.properties.hibernate.show_sql=true

【问题讨论】:

可能对***.com/…有帮助 @RaymondNijland 谢谢你成功了,我们必须确保我们也对客户端密码进行编码。 【参考方案1】:

在以下代码中,您实际上并未使用 Bcrypt 对您的客户端密码进行编码。

clients.inMemory().withClient("my-trusted-client")
        .authorizedGrantTypes("client_credentials", "password")
        .authorities("ROLE_CLIENT","ROLE_TRUSTED_CLIENT").scopes("read","write","trust")
        .resourceIds("oauth2-resource").accessTokenValiditySeconds(5000).secret("bcryptsecret");

使用类似...

accessTokenValiditySeconds(5000).secret("bcrypt$2a$10$ePPx/3nSFjJA2ZQTr2T1rOnpO3hWiWt.GmUj0wL.Xh9sEzUSWrrYm");

【讨论】:

以上是关于Spring Boot BCryptPasswordEncoder 编码密码看起来不像 BCrypt的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Spring Boot 应用程序 pom 同时需要 spring-boot-starter-parent 和 spring-boot-starter-web?

《02.Spring Boot连载:Spring Boot实战.Spring Boot核心原理剖析》

spring-boot-quartz, 依赖spring-boot-parent

spring-boot系列:初试spring-boot

Spring Boot:Spring Boot启动原理分析

Spring Boot:Spring Boot启动原理分析