我使用Spring安全性并使用编码器对密码进行编码。
所以,在我的Spring Security Config中,我自动连接
PasswordEncoder passwordEncoder()
并将其添加到DaoAuthenticationProvider
,这是我的Spring Security配置
package it.besmart.easyparking.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor;
import org.springframework.web.servlet.support.RequestDataValueProcessor;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("customUserDetailsService")
UserDetailsService userDetailsService;
@Autowired
CustomSuccessHandler customSuccessHandler;
@Autowired
CustomAuthenticationFailureHandler customAuthenticationFailureHandler;
@Autowired
DataSource dataSource;
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(authenticationProvider());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/", "/home", "/user/**").permitAll()
.antMatchers("/spots/**", "/parks/**", "/floors/**", "/lights/**", "/sensors/**", "/illumination/**",
"/occupation/**", "/movement/**", "/map/**", "/include/**")
.access("hasRole('USER') or hasRole('ADMIN') or hasRole('PARK')").antMatchers("/admin/**")
.access("hasRole('ADMIN') and hasRole('PARK')").antMatchers("/updatePassword")
.hasAuthority("CHANGE_PASSWORD_PRIVILEGE").
and().formLogin().loginPage("/login").successHandler(customSuccessHandler)
.failureHandler(customAuthenticationFailureHandler).usernameParameter("email")
.passwordParameter("password").and().rememberMe().rememberMeParameter("remember-me")
.tokenRepository(persistentTokenRepository()).tokenValiditySeconds(86400).and().csrf().and()
.exceptionHandling().accessDeniedPage("/Access_Denied");
}
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl tokenRepositoryImpl = new JdbcTokenRepositoryImpl();
tokenRepositoryImpl.setDataSource(dataSource);
return tokenRepositoryImpl;
}
@Bean
public RequestDataValueProcessor requestDataValueProcessor() {
return new CsrfRequestDataValueProcessor();
}
}
当我将数据从我的DTO传递到模型时,我只需执行以下操作
user.setPassword(passwordEncoder.encode(accountDTO.getPassword()));
在我的数据库中,我看到了编码的密码,例如 $ 2a $ 10 $ vVCWjKltOiYO0nPYT1qYI.z4TSk2QJqViDOqRfmoB6BAgldF4vAmm
但是当我尝试登录时,我正在
org.springframework.security.authentication.BadCredentialsException: Bad credentials
当我看到日志时,我发现了这个
o.s.s.c.bcrypt.BCryptPasswordEncoder : Encoded password does not look like BCrypt
我在DB中的密码字段是varchar(100)所以我认为有足够的空间来存储它... 如果我用解码的密码更改数据库中的编码密码,我可以登录...
这是我的CustoUserDetailsService
@Service("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
UserRepository repository;
private final Logger logger = LoggerFactory.getLogger(CustomUserDetailsService.class);
@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
try {
User user = repository.findByEmail(email);
if (user == null) {
throw new UsernameNotFoundException("No user found with username: " + email);
}
logger.debug("user: " + user.toString());
return new org.springframework.security.core.userdetails.User(user.getEmail(),
user.getPassword(), user.isEnabled(), accountNonExpired, credentialsNonExpired, accountNonLocked,
getAuthorities(user));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private List<GrantedAuthority> getAuthorities(User user) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_" + user.getUserProfile().getType()));
// System.out.print("authorities :"+authorities);
return authorities;
}
}
答案 0 :(得分:1)
异常确实来自UserDetailsService.loadUserByUsername()
位置的return
方法,因为错误的实例化User
对象没有收到相应字段的编码密码。
它应该是这样的:
...
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
UserEntity user = userRepository.findByUsername(username);
if (user == null)
throw new UsernameNotFoundException("Bad credentials");
return new User(
user.getUsername(),
user.getPassword(), // shall to be the already BCrypt-encrypted password
getAuthorities());
}
一旦org.springframework.security.authentication.BadCredentialsException: Bad credentials
形成良好的BCrypt hashsum,user.getPassword()
将被抛出。
密码编码器应该像这样注册:
@Autowired
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder);
}
检查出来
答案 1 :(得分:0)
PasswordEncoder应该像这样设置:
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
此外,您还需要为用户和客户端使用passwordEncoder。
您可以查看此存储库https://github.com/dzinot/spring-boot-2-oauth2-authorization-jwt
它使用 Spring Boot 2 ,JWT令牌,用户和客户端存储在数据库中。