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

Использование пользовательского перехватчика Spring MVC Handler для управления сеансами

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

Задача: Медиана двух отсортированных массивов

Даны два отсортированных массива размерами n и m. Найдите медиану слияния этих двух массивов.
Временная сложность решения должна быть O(log(m + n)) ...

ANDROMEDA

1. Введение

В этом уроке мы сосредоточимся на Spring MVC HandlerInterceptor.

В частности, мы покажем более продвинутый вариант использования перехватчиков — мы будем эмулировать логику тайм-аута сеанса , устанавливая пользовательские счетчики и отслеживая сеансы вручную.

Если вы хотите прочитать об основах HandlerInterceptor в Spring, ознакомьтесь с этой статьей .

2. Зависимости Maven

Чтобы использовать Interceptors , вам необходимо включить следующий раздел в раздел зависимостей вашего файла pom.xml :

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.13</version>
</dependency>

Последнюю версию можно найти здесь . Эта зависимость распространяется только на Spring Web, поэтому не забудьте добавить s pring-core и spring-context для полного (минимального) веб-приложения.

3. Пользовательская реализация тайм-аутов сеанса

В этом примере мы настроим максимальное время неактивности для пользователей в нашей системе. По истечении этого времени они автоматически выйдут из приложения.

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

Итак, мы хотим убедиться, что сессия будет аннулирована, если пользователь не активен. Например, если пользователь забыл выйти из системы, счетчик неактивного времени предотвратит доступ к учетной записи неавторизованных пользователей. Для этого нам нужно установить константу для неактивного времени:

private static final long MAX_INACTIVE_SESSION_TIME = 5 * 10000;

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

Теперь нам нужно отслеживать каждый сеанс в нашем приложении, поэтому нам нужно включить этот интерфейс Spring:

@Autowired
private HttpSession session;

Перейдем к методу preHandle() .

3.1. предварительная обработка()

В этот метод мы включим следующие операции:

  • установка таймеров для проверки времени обработки запросов
  • проверка, вошел ли пользователь в систему (используя метод UserInterceptor из этой статьи )
  • автоматический выход из системы, если время неактивного сеанса пользователя превышает максимально допустимое значение

Посмотрим на реализацию:

@Override
public boolean preHandle(
HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
log.info("Pre handle method - check handling start time");
long startTime = System.currentTimeMillis();
request.setAttribute("executionTime", startTime);
}

В этой части кода мы устанавливаем startTime обработки выполнения. С этого момента мы будем отсчитывать количество секунд, чтобы закончить обработку каждого запроса. В следующей части мы предоставим логику для времени сеанса, только если кто-то вошел в систему во время своего HTTP-сеанса:

if (UserInterceptor.isUserLogged()) {
session = request.getSession();
log.info("Time since last request in this session: {} ms",
System.currentTimeMillis() - request.getSession().getLastAccessedTime());
if (System.currentTimeMillis() - session.getLastAccessedTime()
> MAX_INACTIVE_SESSION_TIME) {
log.warn("Logging out, due to inactive session");
SecurityContextHolder.clearContext();
request.logout();
response.sendRedirect("/spring-rest-full/logout");
}
}
return true;

Во-первых, нам нужно получить сессию из запроса.

Затем мы делаем некоторые журналы консоли, о том, кто вошел в систему и сколько времени прошло с тех пор, как пользователь выполняет какую-либо операцию в нашем приложении. Мы можем использовать session.getLastAccessedTime() , чтобы получить эту информацию, вычесть ее из текущего времени и сравнить с нашим MAX_INACTIVE_SESSION_TIME.

Если время превышает допустимое, мы очищаем контекст, выводим запрос из системы и затем (необязательно) отправляем перенаправление в качестве ответа на представление выхода по умолчанию, которое объявлено в файле конфигурации Spring Security.

Чтобы завершить пример счетчиков времени обработки, мы также реализуем метод postHandle() , который описан в следующем подразделе.

3.2. postHandle()

Этот метод реализован только для того, чтобы получить информацию о том, сколько времени ушло на обработку текущего запроса. Как вы видели в предыдущем фрагменте кода, мы устанавливаем время выполнения в модели Spring. Теперь пришло время использовать его:

@Override
public void postHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView model) throws Exception {
log.info("Post handle method - check execution time of handling");
long startTime = (Long) request.getAttribute("executionTime");
log.info("Execution time for handling the request was: {} ms",
System.currentTimeMillis() - startTime);
}

Реализация проста — мы проверяем время выполнения и вычитаем его из текущего системного времени. Только не забудьте присвоить модели значение long .

Теперь мы можем правильно регистрировать время выполнения.

4. Конфигурация перехватчика

Чтобы добавить наш недавно созданный Interceptor в конфигурацию Spring, нам нужно переопределить метод addInterceptors() внутри класса WebConfig , который реализует WebMvcConfigurer:

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SessionTimerInterceptor());
}

Мы можем добиться той же конфигурации, отредактировав наш файл конфигурации XML Spring:

<mvc:interceptors>
<bean id="sessionTimerInterceptor" class="com.foreach.web.interceptor.SessionTimerInterceptor"/>
</mvc:interceptors>

Более того, нам нужно добавить слушателя, чтобы автоматизировать создание ApplicationContext :

public class ListenerConfig implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext sc) throws ServletException {
sc.addListener(new RequestContextListener());
}
}

5. Вывод

В этом руководстве показано, как перехватывать веб-запросы с помощью Spring MVC HandlerInterceptor , чтобы вручную управлять сеансом/тайм-аутом.

Как обычно, все примеры и конфигурации доступны здесь, на GitHub .

5.1. Статьи в серии

Все статьи цикла: