Spring Security всегда возвращает BadCredentialsException в DaoAuthenticationProvider при аутентификации пользователя

В моем приложении Spring Boot у меня есть база данных с пользователями, которую я использую для аутентификации. Однако, когда я передаю правильные учетные данные, Spring Security всегда возвращается BadCredentialsException:

2017-04-22 22: 24: 30.825 DEBUG 6308 --- [io-8080-exec-10] ossadao.DaoAuthenticationProvider: Ошибка аутентификации: пароль не соответствует сохраненному значению 2017-04-22 22:24:30.826 ОТЛАДКА 6308 - - [io-8080-exec-10] waUsernamePasswordAuthenticationFilter: сбой запроса на проверку подлинности: org.springframework.security.authentication.BadCredentialsException: неверные учетные данные

Вот мои бины конфигурации безопасности:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().ignoringAntMatchers("/h2-console").disable()
            .authorizeRequests()
                .antMatchers("/**/favicon.ico").permitAll()
                .antMatchers("/heat/**", "/power/**", "/water/**").permitAll()
                .antMatchers("/webjars/**", "/static/**").permitAll()

            .and().authorizeRequests().antMatchers("/info").permitAll()
            .and().authorizeRequests().antMatchers("/users/**").hasAnyAuthority("ADMIN")

            .and().formLogin()
                    .loginPage("/login")
                    .permitAll()
            .and()
                    .logout()
                    .permitAll()
                    .logoutUrl("/logout")
                    .logoutSuccessUrl("/")
                    .invalidateHttpSession(true)

            .and().exceptionHandling().accessDeniedPage("/access_denied");
}

@Bean
public PasswordEncoder passwordEncoder(StrongPasswordEncryptor passwordEncryptor) {
    PasswordEncoder passwordEncoder = new PasswordEncoder();
    passwordEncoder.setPasswordEncryptor(passwordEncryptor);
    return passwordEncoder;
}

@Bean
public DaoAuthenticationProvider daoAuthenticationProvider(PasswordEncoder passwordEncoder,
                                                           UserDetailsService userDetailsService) {
    DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
    daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
    daoAuthenticationProvider.setUserDetailsService(userDetailsService);
    return daoAuthenticationProvider;
}

@Autowired
public void configureAuthManager(AuthenticationManagerBuilder authenticationManagerBuilder) {
    authenticationManagerBuilder.authenticationProvider(authenticationProvider);
}

Вот мой userDetailsServiceбобы:

@Service("userDetailsService")
public class SpringSecUserDetailsServiceImpl implements UserDetailsService {

    private static final Logger logger = LoggerFactory.getLogger(SpringSecUserDetailsServiceImpl.class);

    private UserService userService;
    private Converter<User, UserDetails> userUserDetailsConverter;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @Autowired
    @Qualifier(value = "userToUserDetails")
    public void setUserUserDetailsConverter(Converter<User, UserDetails> userUserDetailsConverter) {
        this.userUserDetailsConverter = userUserDetailsConverter;
    }

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        User user = userService.findByEmail(email);
        if (user == null) {
            logger.debug("No user found with email " + email);
        }
        return userUserDetailsConverter.convert(user);
    }
}

И мой User в UserDetails преобразователь:

@Component
public class UserToUserDetails implements Converter<User, UserDetails> {

    @Override
    public UserDetails convert(User user) {
        UserDetailsImpl userDetails = new UserDetailsImpl();

        if (user != null) {
            userDetails.setUsername(user.getEmail());
            userDetails.setPassword(user.getEncryptedPassword());
            userDetails.setEnabled(user.getEnabled());

            Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();

            user.getRoles().forEach(role -> authorities.add(new SimpleGrantedAuthority(role.getName())));

            userDetails.setAuthorities(authorities);
        }

        return userDetails;
    }
}

Я также использую библиотеку JASYPT: Java Simplified Encryption. Когда я вписываю адрес электронной почты и пароль пользователя в форму входа в систему, я всегда получаю неверное имя пользователя или пароль, даже когда я передаю правильные учетные данные. Вот мой user Таблица:

Куда я иду не так?

Расширенный стек ошибок:

2017-04-22 13:01:46.105 DEBUG 1336 --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy        : /login at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2017-04-22 13:01:46.105 DEBUG 1336 --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy        : /login at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2017-04-22 13:01:46.105 DEBUG 1336 --- [nio-8080-exec-5] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
2017-04-22 13:01:46.105 DEBUG 1336 --- [nio-8080-exec-5] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
2017-04-22 13:01:46.106 DEBUG 1336 --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy        : /login at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2017-04-22 13:01:46.106 DEBUG 1336 --- [nio-8080-exec-5] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@27d75681
2017-04-22 13:01:46.106 DEBUG 1336 --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy        : /login at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
2017-04-22 13:01:46.106 DEBUG 1336 --- [nio-8080-exec-5] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', GET]
2017-04-22 13:01:46.106 DEBUG 1336 --- [nio-8080-exec-5] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'POST /login' doesn't match 'GET /logout
2017-04-22 13:01:46.106 DEBUG 1336 --- [nio-8080-exec-5] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', POST]
2017-04-22 13:01:46.106 DEBUG 1336 --- [nio-8080-exec-5] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/login'; against '/logout'
2017-04-22 13:01:46.106 DEBUG 1336 --- [nio-8080-exec-5] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', PUT]
2017-04-22 13:01:46.106 DEBUG 1336 --- [nio-8080-exec-5] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'POST /login' doesn't match 'PUT /logout
2017-04-22 13:01:46.106 DEBUG 1336 --- [nio-8080-exec-5] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', DELETE]
2017-04-22 13:01:46.106 DEBUG 1336 --- [nio-8080-exec-5] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'POST /login' doesn't match 'DELETE /logout
2017-04-22 13:01:46.106 DEBUG 1336 --- [nio-8080-exec-5] o.s.s.web.util.matcher.OrRequestMatcher  : No matches found
2017-04-22 13:01:46.106 DEBUG 1336 --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy        : /login at position 5 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2017-04-22 13:01:46.109 DEBUG 1336 --- [nio-8080-exec-5] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/login'; against '/login'
2017-04-22 13:01:46.109 DEBUG 1336 --- [nio-8080-exec-5] w.a.UsernamePasswordAuthenticationFilter : Request is to process authentication
2017-04-22 13:01:46.109 DEBUG 1336 --- [nio-8080-exec-5] o.s.s.authentication.ProviderManager     : Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
Hibernate: 
    select
        user0_.id as id1_2_,
        user0_.dateRegistered as dateRegi2_2_,
        user0_.email as email3_2_,
        user0_.enabled as enabled4_2_,
        user0_.encryptedPassword as encrypte5_2_,
        user0_.lastUpdated as lastUpda6_2_,
        user0_.username as username7_2_ 
    from
        User user0_ 
    where
        user0_.email=?
2017-04-22 13:01:46.115 DEBUG 1336 --- [nio-8080-exec-5] o.s.s.a.dao.DaoAuthenticationProvider    : Authentication failed: password does not match stored value
2017-04-22 13:01:46.116 DEBUG 1336 --- [nio-8080-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:98) ~[spring-security-core-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:166) ~[spring-security-core-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174) ~[spring-security-core-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199) ~[spring-security-core-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94) ~[spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) [spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) [spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) [spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) [spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) [spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.11.jar:8.5.11]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]

2017-04-22 13:01:46.118 DEBUG 1336 --- [nio-8080-exec-5] w.a.UsernamePasswordAuthenticationFilter : Updated SecurityContextHolder to contain null Authentication
2017-04-22 13:01:46.118 DEBUG 1336 --- [nio-8080-exec-5] w.a.UsernamePasswordAuthenticationFilter : Delegating to authentication failure handler org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler@76235ec3
...

ОБНОВЛЕНИЕ 1. Вот мой метод для сохранения пользователя:

@Override
public User saveOrUpdate(User user) {
    if (user.getPassword() != null) {
        user.setEncryptedPassword(encryptionService.encryptString(user.getPassword()));
    }
    return userDao.save(user);
}

И чтение пользователя с его паролем осуществляется в userDetailsService"s loadUserByUsername(String email) метод, который использовал userToUserDetails зависимость (которая в свою очередь содержит строку userDetails.setPassword(user.getEncryptedPassword());):

@Autowired
@Qualifier(value = "userToUserDetails")
public void setUserUserDetailsConverter(Converter<User, UserDetails> userUserDetailsConverter) {
    this.userUserDetailsConverter = userUserDetailsConverter;
}

ОБНОВЛЕНИЕ 2. И прошел следующий тест:

@Test
public void testEncryptedPassword() throws Exception {
    User user = new User();
    String password = "password1";
    user.setEmail("test1@email.com");
    user.setPassword(password);

    User savedUser = userService.saveOrUpdate(user);
    String encryptedPassword = savedUser.getEncryptedPassword();

    System.out.println("======= PassRaw: " + password);
    System.out.println("======= PassEnc: " + encryptedPassword);
    assertTrue(encryptionService.checkPassword(password, encryptedPassword));
}

с результатом:

======= PassRaw: password1
======= PassEnc: TPV54F72y7xdoGZCjBbPhgT1ee2V0X9Uq2v35ooYaQrCOzzOIUgQkGDLs1GCGu6H

0 ответов

Другие вопросы по тегам