1. Общий обзор
В этой статье будет показано, как настроить функцию "Remember Me" в Spring Security, используя не стандартный подход, основанный только на использовании файлов cookie, а более безопасное решение, использующее сохранение.
В качестве краткого пояснения, Spring можно настроить на запоминание данных для входа в систему между сеансами браузера. Это позволяет вам войти на веб-сайт, а затем автоматически вернуться на него при следующем посещении сайта (даже если вы за это время закрыли браузер).
2. Два решения “Remember Me”
Spring предоставляет две немного отличающиеся реализации для решения проблемы. Обе используют UsernamePasswordAuthenticationFilter, используя перехватчики для вызова реализации RememberMeServices.
В предыдущей статье мы уже рассматривали стандартное решение Remember Me, использующее только файл cookie. В этом решении использовался файл cookie под названием remember-me, содержащий имя пользователя, время истечения срока действия и хэш MD5, содержащий пароль. Поскольку файл cookie содержит хэш пароля, это решение потенциально уязвимо в случае перехвата файла cookie.
Имея это в виду, давайте рассмотрим второй подход – использование PersistentTokenBasedRememberMeServices для сохранения сохраненной информации для входа в систему в таблице базы данных между сеансами.
3. Предварительные условия – Создайте таблицу базы данных
Во–первых, нам нужно иметь регистрационную информацию в базе данных – нам нужно создать таблицу для хранения данных:
create table if not exists persistent_logins (
username varchar_ignorecase(100) not null,
series varchar(64) primary key,
token varchar(64) not null,
last_used timestamp not null
);
Это создается автоматически при запуске с помощью следующей конфигурации XML (с использованием базы данных H2 в памяти).:
<!-- create H2 embedded database table on startup -->
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="classpath:/persisted_logins_create_table.sql"/>
</jdbc:embedded-database>
И для полноты картины, вот как настраивается постоянство:
@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:persistence-h2.properties" })
public class DatabaseConfig {
@Autowired private Environment env;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
return dataSource;
}
}
4. Конфигурация пружинной защиты
Первая конфигурация ключа - это конфигурация Http для запоминания (обратите внимание на свойство DataSource):
<http use-expressions="true">
...
<remember-me data-source-ref="dataSource" token-validity-seconds="86400"/>
<http">
Далее – нам нужно настроить фактический RememberMeService и JdbcTokenRepository (который также использует источник данных).:
<!-- Persistent Remember Me Service -->
<beans:bean id="rememberMeAuthenticationProvider" class=
"org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
<beans:constructor-arg value="myAppKey" />
<beans:constructor-arg ref="jdbcTokenRepository" />
<beans:constructor-arg ref="myUserDetailsService" />
</beans:bean>
<!-- Uses a database table to maintain a set of persistent login data -->
<beans:bean id="jdbcTokenRepository"
class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
<beans:property name="createTableOnStartup" value="false" />
<beans:property name="dataSource" ref="dataSource" />
</beans:bean>
<!-- Authentication Manager (uses same UserDetailsService as RememberMeService)-->
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="myUserDetailsService"/>
</authentication-provider>
</authentication-manager>
5. Файл cookie
Как мы уже упоминали, стандартные TokenBasedRememberMeServices хранили хэшированный пароль пользователя в файле cookie.
Это решение – PersistentTokenBasedRememberMeServices использует уникальный идентификатор серии для пользователя. Он идентифицирует первоначальный логин пользователя и остается неизменным каждый раз, когда пользователь автоматически входит в систему в течение этого постоянного сеанса. Он также содержит случайный токен, который восстанавливается каждый раз, когда пользователь входит в систему с помощью сохраняемых функций запоминания.
Эта комбинация случайно сгенерированных серий и токенов сохраняется, что делает атаку методом перебора очень маловероятной.
6. На практике
Чтобы увидеть, как работает механизм "Запомнить меня" в браузере, вы можете:
- Войти в систему с активной функцией "Запомнить меня"
- Закрыть браузер
- Снова открыть браузер и вернуться на ту же страницу.
- Освежить.
Вы по-прежнему будете входить в систему Если функция "Запомнить меня" не активирована, после истечения срока действия файла cookie пользователь должен быть перенаправлен обратно на страницу входа в систему. С помощью функции "Запомнить меня" пользователь остается в системе с помощью нового токена/файла cookie. Вы также можете просмотреть файлы cookie в браузере и сохраненные данные в базе данных (обратите внимание – для этого вам может потребоваться переключиться со встроенной реализации H2).
7. Заключение
В этом руководстве показано, как установить и сконфигурировать сохраняемую в базе данных функциональность маркера "Запомнить меня". Это также продолжение предыдущей статьи, в которой обсуждалась стандартная функциональность, основанная на маркерах cookie. Подход, основанный на базе данных, более безопасен, поскольку данные о пароле не сохраняются в файле cookie, но он требует немного большей настройки.