Spring BCryptPasswordEncoder не получается обновить пароль

Решила в учебный проект добавить возможность смены пароля:

@PostMapping("/settings/change-password")
    public String changePassword(Model model, Principal principal,
                                 @RequestParam String oldPassword,
                                 @RequestParam String newPassword,
                                 @RequestParam String repeatPassword) {

        User user = userService.findByUsername(principal.getName());
        model.addAttribute("user", user);

        log.info("Encoded old password: {}", encoder.encode(oldPassword));
        log.info("Encoded user's password: {}", user.getPassword());

        if (!encoder.matches(encoder.encode(oldPassword), user.getPassword())) {
            model.addAttribute("oldPasswordErr", "Old password is invalid!");
            return "settings";
        } else if (!newPassword.equals(repeatPassword)) {
            model.addAttribute("repeatPasswordErr", "New passwords aren't equals!");
            return "settings";
        }

        user.setPassword(encoder.encode(newPassword));
        userService.saveUser(user);

        return "redirect:/settings";
    }

Но он не проходит первую проверку - пароли не совпадают (11111111 - пароль)

Логи:

2020-12-28 15:58:27.999  INFO 8656 --- [nio-8082-exec-1] c.n.m.controllers.SettingsController     : Encoded old password: $2a$12$NAx6sRYDNGlnVlkJHWXnRupI9F7n5hsuWv69JY39/GoEL.WLUa0xS
2020-12-28 15:58:28.000  INFO 8656 --- [nio-8082-exec-1] c.n.m.controllers.SettingsController     : Encoded user's password: $2a$12$xSARB8s66zhzqNJhU.jruuZCmzdjTDZAJLxxG048.EZEY.6x6GCd2

КАК БЫ, думать долго не пришлось - кодирует он их по разному. Хотя везде используется один бин:

//from my class
private PasswordEncoder encoder;

 @Autowired
    public void setEncoder(PasswordEncoder encoder) {
        this.encoder = encoder;
    }
----
//from config
@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(daoAuthenticationProvider());
    }

    @Bean
    protected PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(12);
    }

    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        daoAuthenticationProvider.setUserDetailsService(service);
        return  daoAuthenticationProvider;
    }

Может, делаю я что-то не так? Может, есть возможность раскодировать его, и потом сравнить? (в интерфейсе методов раскодировки я не нашла) - хотя при логине все работает корректно

введите сюда описание изображения


Ответы (1 шт):

Автор решения: ЮрийСПб

Метод PasswordEncoder#matches в сигнатуре в именах аргументах показывает, что первым аргументом должен быть некодированный пароль. Т.е. вам надо вот так сравнивать пароль пришедший от юзера с тем, что записан в БД:

encoder.matches(oldPassword, user.getPassword())
→ Ссылка