Spring Security 无法识别自己的加密

Posted

技术标签:

【中文标题】Spring Security 无法识别自己的加密【英文标题】:Spring Security doesnt recognize its own encryption 【发布时间】:2018-03-01 17:36:09 【问题描述】:

我在 MsSQL 中遇到 Spring Security 和加密密码问题。在我的 REST 应用程序中,我使用 Spring 4HibernateSpring Data JPA。我正在尝试使用Bcrypt 实现密码加密,但是我只得到了

WARN 4780 --- [io-8080-exec-61] o.s.s.c.bcrypt.BCryptPasswordEncoder
:Encoded password does not look like BCrypt

尝试使用正确的凭据登录时。然后访问显然被拒绝。

我尝试过的或我知道的:

    MS SQL 中的密码正确存储为 Bcrypt 加密字符串 DB 中的密码位置足够长(64 个字符) 将auth.jdbcAuthentication().dataSource(dataSource) 添加到AuthenticationManagerBuilder 并没有改变任何东西。 向 DB 询问密码时,它会返回存储的内容 - Brypt 编码密码。

整个事情有点奇怪,因为我使用相同的 PasswordEncoder 实例对所有内容进行编码。然后它不承认自己的加密。我有什么:

配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter 
        @Autowired
        private RESTAuthenticationEntryPoint authenticationEntryPoint;

        @Autowired
        private RESTAuthenticationFailureHandler authenticationFailureHandler;

        @Autowired
        private RESTAuthenticationSuccessHandler authenticationSuccessHandler;

        @Autowired
        private UserDetailsService userAuthService;

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
                    .csrf().disable()
                    .authorizeRequests()
                        .antMatchers("/home", "/").permitAll()  
                        .antMatchers("/login").permitAll()
                        .antMatchers("/addGame").hasRole("USER")
                    .and()
                    .exceptionHandling()
                        .authenticationEntryPoint(authenticationEntryPoint)
                    .and()
                    .formLogin()
                        .successHandler(authenticationSuccessHandler)
                        .failureHandler(authenticationFailureHandler);

    

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception 
            auth.authenticationProvider(authenticationProvider());
        

        @Bean
        public DaoAuthenticationProvider authenticationProvider() 
            DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
            authProvider.setUserDetailsService(userAuthService);
            authProvider.setPasswordEncoder(encoder());
            return authProvider;
        

        @Bean
        public PasswordEncoder encoder() 
            return new BCryptPasswordEncoder();
        


用户详细信息服务:

@Service 
public class UserAuthService implements UserDetailsService
    @Autowired
    UserDatabaseService userDatabaseService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 
        UserDto user = userDatabaseService.getUserByUsername(username);
        if ( user == null )
            throw new UsernameNotFoundException(username);
         else
            return new MyUserPrincipal(user);
        

    


UserDatabaseService(用 Spring Data 实现):

@Service
public class UserDatabaseService 

    @Autowired
    UserDatabaseRepository userDatabaseRepository;

    @Autowired
    UserToUserDtoConverter userToUserDtoConverter;

    @Autowired
    UserDtoToUserEntityConverter userDtoToUserEntityConverter;

    @Autowired 
    PasswordEncoder passwordEncoder;

    public UserDto getUserByUsername(String username)
        return userToUserDtoConverter.convert( userDatabaseRepository.findByUsername(username) );
    

    public boolean saveUser(UserDto user)
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        if ( userDatabaseRepository.save( userDtoToUserEntityConverter.convert(user) ) != null )
            return true;
         else
            return false;
        
    


说实话,我真的不知道出了什么问题。我一直在关注这两个教程: http://www.baeldung.com/spring-security-authentication-with-a-database http://www.baeldung.com/spring-security-registration-password-encoding-bcrypt

我们将不胜感激所有帮助。

编辑:用于将 DTO 类转换为实体的转换器(反之亦然)

@Service 
public class UserDtoToUserEntityConverter 
    public UserEntity convert(UserDto user)
        return new UserEntity(user.getFirstName(), user.getLastName(), user.getUsername(), user.getPassword() , user.getEmail() );
    

    public Collection<UserEntity> convertAll(Collection<UserDto> fElements)
        Collection<UserEntity> convertedElement =
                fElements.stream()
                        .map(element -> convert(element))
                        .collect(Collectors.toList());
        return convertedElement;
    



@Service 
public class UserToUserDtoConverter implements UserDtoConverter 

    @Override
    public UserDto convert(UserEntity from) 
        return new BaseUserDto( from.getFirstName(), from.getLastName(), 
                                from.getUsername(), from.getPassword(),
                                from.getEmail() );
    


我的用户主体:

public class MyUserPrincipal implements UserDetails
    private UserDto user;

    public MyUserPrincipal(UserDto user) 
        this.user = user;
    

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() 
        throw new UnsupportedOperationException("Not supported yet.");
    

    @Override
    public String getPassword() 
        return user.getPassword();
    

    @Override
    public String getUsername() 
        return user.getUsername();
    

    @Override
    public boolean isAccountNonExpired() 
        return true;
    

    @Override
    public boolean isAccountNonLocked() 
        return true;
    

    @Override
    public boolean isCredentialsNonExpired() 
        return true;
    

    @Override
    public boolean isEnabled() 
        return true;
    




【问题讨论】:

@dur 我已经编辑了原始问题,如果您能看一下,我将不胜感激。那些转换器你做的不多。 是的,我已经尝试过了 - 它返回正确编码的密码。但是,不仅编码有问题 - 没有它我也无法登录。Spring Data 是否讨厌 Hibernate 或其他什么......? MyUserPrincipal 是实现 Spring Security 的“UserDetails”接口的类。我已经在问题中添加了代码,它也没有真正做太多...... 【参考方案1】:

如果有人想知道问题出在哪里 - 数据库返回密码和末尾的空格......这就是为什么它永远无法验证,提供的密码总是与存储在数据库中的密码“不同”......上帝该死。

【讨论】:

以上是关于Spring Security 无法识别自己的加密的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot + Thymeleaf Security 无法识别

无法在 Spring Security 中识别身份验证提供者 user-service-ref

Spring Security PasswordEncoder

Spring Security 自定义登录认证

Grails Spring-Security-Core 插件 - 无法验证用户

Spring security Userdetails 无法转换为我自己的用户实现