Я слежу за этот учебник по Baeldung и не вижу никаких различий (кроме, может быть, предварительно сгенерированного шаблона страницы входа в систему), но я все еще получаю BadCredentialsException при попытке войти в систему с жестко заданной комбинацией пользователь / пароль, которая, как я уже подтвердил, является в БД и пароль там зашифрован.
Вот мой код, дайте мне знать, если понадобится больше:
SecurityConfig:
@Component
@EnableWebSecurity
@SuppressWarnings("unused")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyUserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/css/**").permitAll()
.antMatchers("/error").permitAll()
.antMatchers("/action/**").hasRole("USER")
.antMatchers("/action_template/**").hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/login").failureUrl("/login-error");
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider());
}
@Bean
public DaoAuthenticationProvider authProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
MyUserDetailsService:
@Service
@Transactional
@SuppressWarnings("unused")
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
User user = userRepository.findByEmail(email);
if (user == null) {
throw new UsernameNotFoundException(
"No user found with username: " + email);
}
final List<GrantedAuthority> authorities = new ArrayList<>();
user.getRoles().forEach((r) -> authorities.add(new SimpleGrantedAuthority(r)));
return new org.springframework.security.core.userdetails.User(
user.getEmail(),
user.getPassword().toLowerCase(),
true,
true,
true,
true,
authorities
);
}
}
Обновлено:
Вот трассировка стека
2018-11-14 13:52:05.785 DEBUG 2100 --- [nio-8090-exec-5] w.a.UsernamePasswordAuthenticationFilter : Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials
org.springframework.security.authentication.BadCredentialsException: Bad credentials
at org.springframework.security.authentication.dao.DaoAuthenticationProvider.additionalAuthenticationChecks(DaoAuthenticationProvider.java:93)
at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:166)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199)
at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:124)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Я также отредактировал свой SecurityConfig и добавил .antMatchers("/error").permitAll(), но это не помогло
Обновлено еще раз:
Вот Репозиторий Github, он должен дать больше информации. Я понятия не имею, как это диагностировать дальше ...




Проблема, похоже, связана с тем, как вы регистрируете свой закодированный пароль. Попробуйте зарегистрировать это так:
@Autowired
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder);
}
В configure(HttpSecurity http) после .antMatchers("/css/**").permitAll()
Пока безуспешно ... Должен ли я сделать репозиторий Github общедоступным и связать его?
Spring Boot может автоматически подбирать / создавать все необходимые bean-компоненты, поэтому вы можете упростить SecurityConfig следующим образом (он найдет ваш UserDetailsService и создаст DaoAuthenticationProvider по умолчанию, если такой bean-компонент не определен):
@Component
@EnableWebSecurity
@SuppressWarnings("unused")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/css/**").permitAll()
.antMatchers("/error").permitAll()
.antMatchers("/action/**").hasRole("USER")
.antMatchers("/action_template/**").hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/login").failureUrl("/login-error");
}
}
Также определите bean-компонент passwordEncoder в другом классе конфигурации (однако я не совсем уверен, нужен ли он также):
@Configuration
public class BeanConfiguration {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Я исправил это;) В любом случае спасибо за подсказку, я проверю, что вы сказали о UserDetailsService!
Я ... в недоумении.
Я нашел проблему. Я не знаю, почему я подумал, что это нормально, и я не знаю, почему он там есть в руководстве, но даже если пароль - «пароль», user.getPassword().toLowerCase() использует хэш BCrypt в нижнем регистре, а не фактический пароль.
Удаление .toLowerCase() исправляет это.
лол, я этого не заметил. Вам все равно следует подумать об упрощении конфигурации, как я предложил в своем ответе.
Где ты это разместил?