Spring Security 5 — Неверные учетные данные при входе, несмотря на правильный адрес электронной почты и пароль

#java #spring-boot #authentication #spring-security #bcrypt

#java #spring-boot #аутентификация #spring-безопасность #bcrypt

Вопрос:

Я пытался решить это с неделю и перепробовал все сообщения и все еще не мог получить эту работу. Мой класс SecurityConfiguration:

 @Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    private final BCryptPasswordEncoder bCryptPasswordEncoder;
    private final DataSource dataSource;

    @Value("${spring.queries.users-query}")
    private String usersQuery;

    @Value("${spring.queries.roles-query}")
    private String rolesQuery;


    public SecurityConfiguration(BCryptPasswordEncoder bCryptPasswordEncoder, DataSource dataSource) {
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
        this.dataSource = dataSource;
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.
                jdbcAuthentication()
                .passwordEncoder(bCryptPasswordEncoder)
                .usersByUsernameQuery(usersQuery)
                .authoritiesByUsernameQuery(rolesQuery)
                .dataSource(dataSource)
                ;


    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {



        http.authorizeRequests().antMatchers("/","/h2-console/**","/registration","/login").permitAll()
                .antMatchers("/offer/**").access("hasRole('USER') or hasRole('ADMIN')")
                .and()
                .formLogin()
                .loginPage("/login").failureUrl("/login?error=true")
                .defaultSuccessUrl("/")
                .usernameParameter("email")
                .passwordParameter("password")
                .and().logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .logoutSuccessUrl("/").and().exceptionHandling()
                .accessDeniedPage("/access-denied");
        http.csrf().disable();
        http.headers().frameOptions().disable();

    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web
                .ignoring()
                .antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**");
    }
}
  

и у меня есть класс WebMvcConfiguration следующим образом:

 @Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        return bCryptPasswordEncoder;
    }
}
  

Я просто продолжаю получать «Неверные учетные данные» и что пароль не соответствует записям. Я вижу хэшированный пароль в базе данных и настраиваю точку отладки непосредственно перед строкой, где класс DaoAuthenticationProvider выдает это исключение (метод additionalAuthenticationChecks), и, насколько я могу видеть, данные пользователя из базы данных поступают правильно, но он не показывает представленный пароль при входе в систему как закодированный…

Мой контроллер входа в систему выглядит следующим образом:

 @Controller
public class LoginController {

    private final UserAccountService userAccountService;


    public LoginController(UserAccountService userAccountService) {
        this.userAccountService = userAccountService;
    }

    @GetMapping("/login")
    public ModelAndView login( Error error){
        ModelAndView modelAndView = new ModelAndView();
        if (error != null) {
            modelAndView.setViewName("error page");
        }
        modelAndView.setViewName("login");
        return modelAndView;
    }

    @PostMapping("/registration")
    public ModelAndView createNewUser(@Valid UserAccount user, BindingResult bindingResult) {
        ModelAndView modelAndView = new ModelAndView();
        UserAccount userExists = userAccountService.findUserByEmail(user.getEmail());
        if (userExists != null) {
            bindingResult
                    .rejectValue("email", "error.user",
                            "There is already a user registered with the email provided");
        }
        if (bindingResult.hasErrors()) {
            modelAndView.setViewName("registration");
        } else {
            userAccountService.saveOrUpdate(user);
            modelAndView.addObject("successMessage", "User has been registered successfully");
            modelAndView.addObject("user", new UserAccount());
            modelAndView.setViewName("registration");

        }
        return modelAndView;
    }

    @GetMapping("/admin/home")
    public ModelAndView home(){
        ModelAndView modelAndView = new ModelAndView();
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        UserAccount user = userAccountService.findUserByEmail(auth.getName());
        modelAndView.addObject("userName", "Welcome "   user.getFirstName()   " "
                  user.getLastName()   " ("   user.getEmail()   ")");
        modelAndView.addObject("adminMessage","Content Available Only for Users with Admin Role");
        modelAndView.setViewName("admin/home");
        return modelAndView;
    }

}
  

Мои SQL-запросы также работают корректно, я опробовал их на консоли H2…

как вы думаете, я делаю неправильно?

Комментарии:

1. $ 2a $ 10 $HwZisjNuFqVpiNeq399cKOUPZH8LVsKbQS4sniZeyewixc4a3eRP2 — это хэш, а 1234 — это то, что я ввожу при входе в систему..

Ответ №1:

Хорошо, я нашел виновника:

При запуске приложения я заполнял базу данных некоторыми тестовыми данными и понял, что обновлял учетные записи пользователей, в которых пароли были перекодированы…

Как только я сократил использование метода «saveOrUpdate» класса UserAccount, я смог войти в систему.