【发布时间】:2018-03-01 17:36:09
【问题描述】:
我在 MsSQL 中遇到 Spring Security 和加密密码问题。在我的 REST 应用程序中,我使用 Spring 4、Hibernate 和 Spring 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”接口的类。我已经在问题中添加了代码,它也没有真正做太多......
标签: hibernate spring-security spring-data-jpa bcrypt