У меня есть веб-приложение с spring-boot 2.0.1, защищенное spring-security. Я использую PersistentTokenRepository
для Remember-Me и храню токены в базе данных MySQL.
В лог-файлах сервера я вижу довольно много стековых трасс с CookieTheftException
с. Их так много, что мне трудно поверить, что настоящие куки-файлы украдены, но допускается какая-то неверная конфигурация. Добавление некоторого анализирующего кода, похоже, затрагивает только мобильные браузеры.
Servlet.service() for servlet [dispatcherServlet] in context with path [/r] threw exception
org.springframework.security.web.authentication.rememberme.CookieTheftException: Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack.
at org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices.processAutoLoginCookie(PersistentTokenBasedRememberMeServices.java:119) ~[spring-security-web-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
Ручное тестирование не смогло воспроизвести это. Удаление cookie-файла сеанса, но сохранение cookie-файла запомнить и отправка запроса на ограниченный URL-адрес приводит к обычному сеансу аутентификации.
Вот соответствующие части моей конфигурации безопасности:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {
@Configuration
public static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private RememberMeServices rememberMeServices;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.rememberMe()
.key(rememberMeKey)
.rememberMeServices(rememberMeServices);
;
}
}
/**
* Key for RememberMeServices and RememberMeAuthenticationProvider.
*/
private static final String rememberMeKey = "...";
@Bean
public RememberMeServices rememberMeServices(UserDetailsService userDetailsService, PersistentTokenRepository persistentTokenRepository) {
PersistentTokenBasedRememberMeServices rememberMeServices = new AnalyzingPersistentTokenBasedRememberMeServices(
rememberMeKey, userDetailsService, persistentTokenRepository);
rememberMeServices.setTokenValiditySeconds((int) Duration.of(366L, ChronoUnit.DAYS).toSeconds());
return rememberMeServices;
}
@Bean
public PersistentTokenRepository persistentTokenRepository(JdbcTemplate jdbcTemplate) {
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
tokenRepository.setJdbcTemplate(jdbcTemplate);
return tokenRepository;
}
}
То, что AnalyzingPersistentTokenBasedRememberMeServices
- это PersistentTokenBasedRememberMeServices
с некоторым дополнительным входом в систему processAutoLoginCookie
.
Другой особенностью является то, что я использую пользовательский AuthenticationProvider
и предоставляю UserDetailsService
только для RememberMe. Но, как сказано выше, ручное тестирование работает просто отлично Тем не менее пользователи сообщают, что они слишком часто выходят из системы (время ожидания сеанса составляет 24 часа).
Кто-нибудь испытывал нечто подобное и нашел решение? Я скучаю по какой-то важной конфигурации?