为什么Spring安全给密码编码器的密码是空的? [英] why does spring security give empty password to password encoder?

查看:33
本文介绍了为什么Spring安全给密码编码器的密码是空的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用带有bcrypt密码编码器的Spring security进行身份验证。当我想登录时,Spring安全会使用JPA正确获取用户数据,但为了检查原始密码和编码密码,它会将空字符串作为编码密码提供给密码编码器。

Spring安全配置:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    @Qualifier("userDetailsServiceImpl")
    private UserDetailsService userDetailsService;

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

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
        auth.userDetailsService(userDetailsService)
        .passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/").hasAuthority("USER")
                .antMatchers("/css/**","/font/**","/js/**","/image/**").permitAll()
                .antMatchers("/register").permitAll()
                .and().formLogin().loginPage("/login").successForwardUrl("/").permitAll()
                .and().logout().logoutSuccessUrl("/login");
    }
}

userDetailsServise:

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    private UserRepository userRepo;

    @Autowired
    public UserDetailsServiceImpl(UserRepository userRepo){
        this.userRepo = userRepo;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
         User user = userRepo.findByUsername(username);
         if(user != null) {
             System.out.println(user.toString());
             return user;
         }
         throw new UsernameNotFoundException("User "+ username +" not found");
    }
}

用户实体:

@Entity
@Table(name = "users")
public class User implements UserDetails {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq")
    @SequenceGenerator(name = "user_seq", sequenceName = "users_id_seq",allocationSize = 1)
    private long id;

    @NotEmpty
    @Column(nullable = false, unique=true)
    private String username;

    @Email
    @Column(nullable = false, updatable = false, unique = true)
    private String email;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    private boolean enabled;

    @CreationTimestamp
    @Column(name = "creation_time")
    private Timestamp creationTime;

    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(joinColumns = @JoinColumn(name="user_id"))
    private List<Authority> authorities;
...

日志:

2019-05-31 19:51:58.888 DEBUG 7181 --- [nio-8080-exec-3] w.a.UsernamePasswordAuthenticationFilter : Request is to process authentication
2019-05-31 19:51:58.889 DEBUG 7181 --- [nio-8080-exec-3] o.s.s.authentication.ProviderManager     : Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
2019-05-31 19:51:59.245 DEBUG 7181 --- [nio-8080-exec-3] tor$SharedEntityManagerInvocationHandler : Creating new EntityManager for shared EntityManager invocation
2019-05-31 19:51:59.388  INFO 7181 --- [nio-8080-exec-3] o.h.h.i.QueryTranslatorFactoryInitiator  : HHH000397: Using ASTQueryTranslatorFactory
Hibernate: select user0_.id as id1_1_, user0_.creation_time as creation2_1_, user0_.email as email3_1_, user0_.enabled as enabled4_1_, user0_.password as password5_1_, user0_.username as username6_1_ from users user0_ where user0_.username=?
Hibernate: select authoritie0_.user_id as user_id1_0_0_, authoritie0_.authorities as authorit2_0_0_ from user_authorities authoritie0_ where authoritie0_.user_id=?
User{
id=8
, username='username'
, email='mail@example.com'
, password='$2a$10$TyQ8x0KUP9Nrtzo2ljfNfei4S3h1kFpYEb5/CDs2lKSDzMJECQ./q'
, enabled=true
, creationTime=2019-05-31 19:32:12.948
, authorities=[USER]}
2019-05-31 19:51:59.758  WARN 7181 --- [nio-8080-exec-3] o.s.s.c.bcrypt.BCryptPasswordEncoder     : Empty encoded password
2019-05-31 19:51:59.758 DEBUG 7181 --- [nio-8080-exec-3] o.s.s.a.dao.DaoAuthenticationProvider    : Authentication failed: password does not match stored value
2019-05-31 19:51:59.773 DEBUG 7181 --- [nio-8080-exec-3] w.a.UsernamePasswordAuthenticationFilter : Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials

我创建了以下密码编码器,并计算出Spring Security将一个空字符串作为编码密码提供给密码编码器。

@Component
public class MyPasswordEncoder implements PasswordEncoder {

    BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

    @Override
    public String encode(CharSequence rawPassword) {
        return encoder.encode(rawPassword);
    }

    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {

        System.out.println("raw password: " + rawPassword + "	 encoded passwod: "+ encodedPassword);

        return encoder.matches(rawPassword,encodedPassword);
    }
}

使用自定义密码编码器的日志:

2019-06-01 03:19:52.759 DEBUG 7870 --- [nio-8080-exec-5] w.a.UsernamePasswordAuthenticationFilter : Request is to process authentication
2019-06-01 03:19:52.759 DEBUG 7870 --- [nio-8080-exec-5] o.s.s.authentication.ProviderManager     : Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
2019-06-01 03:19:53.036 DEBUG 7870 --- [nio-8080-exec-5] tor$SharedEntityManagerInvocationHandler : Creating new EntityManager for shared EntityManager invocation
2019-06-01 03:19:53.095  INFO 7870 --- [nio-8080-exec-5] o.h.h.i.QueryTranslatorFactoryInitiator  : HHH000397: Using ASTQueryTranslatorFactory
Hibernate: select user0_.id as id1_1_, user0_.creation_time as creation2_1_, user0_.email as email3_1_, user0_.enabled as enabled4_1_, user0_.password as password5_1_, user0_.username as username6_1_ from users user0_ where user0_.username=?
Hibernate: select authoritie0_.user_id as user_id1_0_0_, authoritie0_.authorities as authorit2_0_0_ from user_authorities authoritie0_ where authoritie0_.user_id=?
User{
id=8
, username='username'
, email='mail@example.com'
, password='$2a$10$TyQ8x0KUP9Nrtzo2ljfNfei4S3h1kFpYEb5/CDs2lKSDzMJECQ./q'
, enabled=true
, creationTime=2019-05-31 19:32:12.948
, authorities=[USER]}
raw password: password   encoded passwod: null
2019-06-01 03:19:53.413  WARN 7870 --- [nio-8080-exec-5] o.s.s.c.bcrypt.BCryptPasswordEncoder     : Empty encoded password
2019-06-01 03:19:53.413 DEBUG 7870 --- [nio-8080-exec-5] o.s.s.a.dao.DaoAuthenticationProvider    : Authentication failed: password does not match stored value
2019-06-01 03:19:53.415 DEBUG 7870 --- [nio-8080-exec-5] w.a.UsernamePasswordAuthenticationFilter : Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials

GitHub上的完整源代码:https://github.com/yrostami/spring_sample

推荐答案

BCryptPasswordEncoder将比较来自加载的用户的密码与从登录表单输入的密码是否匹配。如果前者为空,则给出Empty encoded password警告。

因此,通过查看您如何加载用户,您的UserDetailsService将始终返回Usera null password,因为您将其硬编码在getPassword()中(顺便说一下,getUsername()也有同样的问题)。因此,更改为以下内容应该可以解决此问题:

@Override
public String getPassword() {
    return this.password;
}

@Override
public String getUsername() {
    return this.username;
}

这篇关于为什么Spring安全给密码编码器的密码是空的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆