Я разрабатываю приложение Spring Boot с Vaadin для внешнего интерфейса и столкнулся с проблемой, из-за которой пользователи не могут войти в систему. Несмотря на регистрацию пользователей и сохранение их в базе данных с зашифрованными паролями, попытки входа всегда терпят неудачу, что приводит к сообщению «Невозможно войти. Проверьте, правильно ли вы ввели свой адрес электронной почты и пароль». сообщение об ошибке.
Среда
- Spring Boot: 3.2.5< /p>
- Ваадин: 24.3.11
- Java: 17
- База данных: MySQL
Код: Выделить всё
@Configuration
@EnableWebSecurity
public class SecurityConfig {
private static final Logger logger = Logger.getLogger(SecurityConfig.class.getName());
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public UserDetailsService userDetailsService(UserService userService) {
return userService;
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
logger.info("Configuring Security Filter Chain");
http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/login", "/register", "/error").permitAll()
.requestMatchers("/api/todos/**").authenticated()
.requestMatchers("/todos/**").authenticated()
.requestMatchers("/api/users/**").authenticated()
.anyRequest().permitAll())
.formLogin(form -> form
.loginPage("/login")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/todos", true)
.failureUrl("/login?error=true")
.permitAll())
.logout(logout -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout=true")
.permitAll());
logger.info("Security Filter Chain configured");
return http.build();
}
}
Код: Выделить всё
@Service
public class UserService implements UserDetailsService {
private static final Logger logger = Logger.getLogger(UserService.class.getName());
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
@Autowired
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
public List findAllUsers() {
return userRepository.findAll();
}
public Optional findUserById(UUID id) {
return userRepository.findById(id);
}
public Optional findUserByEmail(String email) {
return userRepository.findByEmail(email.toLowerCase());
}
public User saveUser(User user) {
logger.info("Saving user with email: " + user.getEmail());
String originalPassword = user.getPassword();
user.setPassword(passwordEncoder.encode(user.getPassword()));
logger.info("Original password: " + originalPassword);
logger.info("Encoded password: " + user.getPassword());
user.setEmail(user.getEmail().toLowerCase());
User savedUser = userRepository.save(user);
logger.info("User saved with ID: " + savedUser.getId());
return savedUser;
}
public void deleteUser(UUID id) {
userRepository.deleteById(id);
}
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
logger.info("Loading user by email: " + email);
User user = userRepository.findByEmail(email.toLowerCase())
.orElseThrow(() -> {
logger.warning("User not found with email: " + email);
return new UsernameNotFoundException("User not found with email: " + email);
});
logger.info("User found: " + user.getEmail() + ", password: " + user.getPassword());
return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), Collections.emptyList());
}
}
Код: Выделить всё
@Route("login")
@PageTitle("Login | Todo")
@CssImport("./styles/todo-view.css")
@AnonymousAllowed
public class LoginView extends VerticalLayout implements BeforeEnterObserver {
private static final Logger logger = Logger.getLogger(LoginView.class.getName());
private final LoginForm loginForm = new LoginForm();
public LoginView() {
addClassName("login-view");
setSizeFull();
loginForm.setForgotPasswordButtonVisible(false);
loginForm.setAction("login");
loginForm.setI18n(createLoginI18n());
VerticalLayout loginFormContainer = new VerticalLayout();
loginFormContainer.addClassName("login-form-container");
loginFormContainer.setSizeUndefined();
loginFormContainer.setAlignItems(Alignment.CENTER);
Anchor registerLink = new Anchor("register", "No account yet? Register here.");
registerLink.addClassName("login-link");
loginFormContainer.add(new H1("TodoApp Login"), loginForm, registerLink);
add(loginFormContainer);
}
private LoginI18n createLoginI18n() {
LoginI18n i18n = LoginI18n.createDefault();
i18n.getForm().setUsername("E-mail");
i18n.getForm().setTitle("Log in");
i18n.getForm().setSubmit("Log in");
i18n.getForm().setPassword("Password");
i18n.getErrorMessage().setTitle("Unable to log in");
i18n.getErrorMessage().setMessage("Check that you have entered your email and password correctly.");
return i18n;
}
@Override
public void beforeEnter(BeforeEnterEvent event) {
if (event.getLocation().getQueryParameters().getParameters().containsKey("error")) {
loginForm.setError(true);
logger.warning("Login attempt failed.");
}
}
}
- Регистрация пользователя работает, данные пользователя сохраняется в базе данных с зашифрованным паролем.
- При попытке войти в систему с учетными данными зарегистрированного пользователя происходит сбой с сообщением: " Невозможно войти в систему. Убедитесь, что вы правильно ввели свой адрес электронной почты и пароль."
- Журналы отладки показывают, что loadUserByUsername в UserService не вызывается при попытке входа в систему.
- Регистрация пользователей и кодирование паролей:
- Проверено, что пользователи регистрируются правильно и пароли кодируется с помощью BCryptPasswordEncoder. Ожидается, что вход будет работать с учетными данными зарегистрированного пользователя.
- Конфигурация безопасности: >
- Настроено [/b] в
Код: Выделить всё
UserDetailsService[/b] для использованияКод: Выделить всё
SecurityConfig[/b] метод, который будет вызываться при попытке входа в систему.Код: Выделить всё
UserService. Ожидал loadUserByUsername
- Настроено
- Конфигурация формы входа:
- Установите URL-адрес действия формы входа в соответствии с ожидаемым Spring Security. Ожидается, что вход будет успешным с использованием правильных учетных данных.
- Журнал отладки:< /p>
- Добавлены журналы отладки для проверки правильности [/b] вызывается и возвращает правильные данные пользователя. Ожидается, что журналы будут отражать успешные попытки входа в систему.
Код: Выделить всё
loadUserByUsername
- Добавлены журналы отладки для проверки правильности
Подробнее здесь: https://stackoverflow.com/questions/785 ... icate-user