Перейти к основному содержимому

Spring Security — постоянно помните меня

· 4 мин. чтения

Задача: Сумма двух чисел

Напишите функцию twoSum. Которая получает массив целых чисел nums и целую сумму target, а возвращает индексы двух чисел, сумма которых равна target. Любой набор входных данных имеет ровно одно решение, и вы не можете использовать один и тот же элемент дважды. Ответ можно возвращать в любом порядке...

ANDROMEDA

1. Обзор

В этой статье будет показано, как настроить функцию «Запомнить меня» в Spring Security — используя не стандартный подход только к файлам cookie, а более безопасное решение, использующее постоянство .

В качестве краткого введения: Spring можно настроить так, чтобы он запоминал данные для входа между сеансами браузера. Это позволяет вам войти на веб-сайт, а затем автоматически войти в систему при следующем посещении сайта (даже если вы тем временем закрыли браузер).

2. Два решения «Запомнить меня»

Spring предоставляет две немного разные реализации для решения проблемы. Оба используют UsernamePasswordAuthenticationFilter , используя ловушки для вызова реализации RememberMeServices .

Стандартное решение «Запомнить меня», использующее только cookie, мы уже рассматривали в предыдущей статье . В этом решении использовался файл cookie с именем « запомнить меня», содержащий имя пользователя, время истечения срока действия и хэш MD5, содержащий пароль. Поскольку он содержит хэш пароля, это решение потенциально уязвимо , если файл 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. Конфигурация безопасности Spring

Первая ключевая конфигурация — это конфигурация Remember-Me 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. Печенье

Как мы уже упоминали, стандартный TokenBasedRememberMeServices хранил хешированный пароль пользователя в файле cookie.

Это решение — PersistentTokenBasedRememberMeServices использует уникальный идентификатор серии для пользователя . Это идентифицирует первоначальный вход пользователя в систему и остается постоянным каждый раз, когда пользователь автоматически входит в систему во время этого постоянного сеанса. Он также содержит случайный токен , который обновляется каждый раз, когда пользователь входит в систему с помощью постоянных функций запоминания.

Эта комбинация случайно сгенерированных серий и токенов сохраняется, что делает атаку грубой силы маловероятной.

6. На практике

Чтобы увидеть, как работает механизм «запомнить меня» в браузере, вы можете:

  1. Войти с активной функцией «Запомнить меня»
  2. Закройте браузер
  3. Снова откройте браузер и вернитесь на ту же страницу. Обновить.
  4. Вы по-прежнему будете авторизованы

Если функция «Запомнить меня» не активна , после истечения срока действия файла cookie пользователь должен быть перенаправлен обратно на страницу входа. С функцией «Запомнить меня » пользователь теперь остается в системе с помощью нового токена/куки.

Вы также можете просматривать файлы cookie в браузере и сохраненные данные в базе данных (примечание — для этого вы можете отказаться от встроенной реализации H2).

7. Заключение

В этом учебном пособии показано, как установить и настроить функцию сохранения токена «Запомнить меня» в базе данных . Это также продолжение предыдущей статьи, в которой обсуждалась стандартная функциональность на основе токена cookie . Подход с базой данных более безопасен, поскольку сведения о пароле не сохраняются в файле cookie, но требует немного большей настройки.

Реализацию этого учебного пособия по Spring Security REST можно найти в проекте GitHub — это проект на основе Eclipse, поэтому его легко импортировать и запускать как есть.