Вопрос или проблема
Я сталкиваюсь с странной проблемой. Мое приложение на Spring Boot 2 всегда имеет проблемы с входом после нескольких дней работы. Если я перезапускаю сервер, то оно начинает работать, но через пару дней всегда реагирует с неправильным паролем (да, пароль был правильным).
Есть идеи, куда мне следует посмотреть? Спасибо!
Вот код:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers(headers -> headers.frameOptions().disable());
http.authorizeRequests(requests -> requests
.antMatchers("/sitemap.xml", ....)
.permitAll());
http.authorizeRequests(requests -> requests.anyRequest().authenticated()).formLogin(login -> login
.loginPage("/login")
.failureHandler(new CustomAuthenticationFailureHandler())
.authenticationDetailsSource(authenticationDetailsSource).defaultSuccessUrl("/filter").permitAll())
.rememberMe(me -> me.key("something").rememberMeCookieName("something-remember-me")
.rememberMeParameter("remember-me").userDetailsService(userServiceDetailImpl)
.tokenValiditySeconds(24 * 3600)
.tokenRepository(persistentTokenRepository()))
.logout(logout -> logout
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login?logout")
.permitAll())
.oauth2Login(login -> login
.loginPage("/login")
.userInfoEndpoint()
.userService(oAuth2UserService).and().successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
CustomOAuth2User oauthUser = (CustomOAuth2User) authentication.getPrincipal();
userService.processOAuthPostLogin(oauthUser, request);
response.sendRedirect("/filter");
}
}));
}
@Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity.httpFirewall(new StrictHttpFirewall());
}
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Bean
public ServletListenerRegistrationBean httpSessionEventPublisher() {
return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
}
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
tokenRepository.setDataSource(dataSource);
return tokenRepository;
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider());
}
@Bean
public HttpSessionEventPublisher myhttpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
@Bean
public MappedInterceptor myInterceptor() {
return new MappedInterceptor(null, sameSiteCookieServiceInterceptor);
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public DaoAuthenticationProvider authProvider() {
CustomAuthenticationProvider authProvider = new CustomAuthenticationProvider();
authProvider.setUserDetailsService(userServiceDetailImpl);
authProvider.setPasswordEncoder(new BCryptPasswordEncoder());
return authProvider;
}
}
и
Ответ или решение
Проблема, с которой вы сталкиваетесь — это частая «ложная уверенность» в том, что пароль неверный после нескольких дней работы сервера Spring Boot 2. Давайте подробно рассмотрим возможные причины и пути их решения.
1. Проблемы с состоянием HTTP-сессий
Одной из наиболее вероятных причин вашего вопроса может быть неправильное управление сессиями. Если ваше приложение хранит состояния сессий в памяти, то по мере увеличения количества сессий и их увеличенного времени жизни, могут возникнуть конфликты.
- Решение: Убедитесь, что вы используете
HttpSessionEventPublisher
, который вы уже объявили в конфигурации. Это дает вам конкурирующий механизм для управления сессиями.
@Bean
public ServletListenerRegistrationBean<HttpSessionEventPublisher> httpSessionEventPublisher() {
return new ServletListenerRegistrationBean<>(new HttpSessionEventPublisher());
}
2. Проблемы с таймаутами
Тайм-аут сессии может быть другой причиной. Если ваша сессия истекает, а ваша аутентификация не обновляется должным образом, это может вызвать повторные попытки входа в систему с неверными данными.
- Решение: Проверьте, как вы настраиваете тайм-ауты сессии. Возможно, стоит установить их повыше в конфигурации сервера.
3. Настройки кеширования
Во многих случаях кеширование аутентификации может быть проблемой. Например, если вы используете remember-me
параметры, важно убедиться, что система не запоминает устаревшие токены, что может привести к неверным попыткам входа.
.rememberMe(me -> me
.key("something")
.tokenValiditySeconds(24 * 3600) // Один день
.userDetailsService(userServiceDetailImpl));
- Решение: Убедитесь, что ваши токены действительны в требуемые сроки, и, возможно, увеличьте продолжительность жизни токенов.
4. Работы с паролями и шифрованием
Использование BCryptPasswordEncoder
— это стандартный подход, однако, если у вас есть какие-либо другие механизмы управления паролями, они могут конфликтовать.
- Решение: Проверьте, не теряете ли вы пароли или их хэширование при рестарте приложения или в процессе работы. Убедитесь, что ваша база данных целиком функционирует и хранит актуальные данные пользователей.
5. Логи и отладка
Подробная диагностика приложения может помочь выявить причину проблемы. Включите более детализированное логирование, особенно в секции аутентификации.
- Решение: Используйте
SLF4J
или другие логирующие библиотеки для записи аутентификации и проблем с сессиями.
6. Устойчивость к сбоям
Приложение должно быть устойчиво к сбоям, в том числе к отключениям базы данных или повреждениям на уровне сессий. Убедитесь, что ваши DAO и репозитории настроены для обработки исключений.
Заключение
Ваш случай с ложным паролем после нескольких дней работы может быть результатом множества факторов, начиная от управления сессиями и заканчивая хранением паролей в базе данных. Проверьте все описанные выше аспекты и примените предложенные решения. Постепенно, через проверку, вы сможете найти основную причину проблемы. Если вы продолжаете испытывать трудности, может быть полезным использовать инструменты мониторинга, такие как Spring Boot Actuator, для инспекции текущего состояния вашего приложения в процессе его работы.