Подтвердить что ты не робот

Что такое OnePerRequestFilter?

Документация говорит org.springframework.web.filter.OncePerRequestFilter "гарантирует, что будет выполняться только один раз за запрос". При каких обстоятельствах фильтр может выполняться более одного раза за запрос?

4b9b3361

Ответ 1

При каких обстоятельствах фильтр может выполняться несколько раз за запрос?

Вы можете иметь фильтр в цепочке фильтров более одного раза.

Запрос может быть отправлен другому (или одному и тому же) сервлету с помощью диспетчера запросов.


Распространенным вариантом использования является Spring Security, где функции аутентификации и контроля доступа обычно реализуются в виде фильтров, которые располагаются перед сервлетами основного приложения. Когда запрос отправляется с помощью диспетчера запросов, он должен снова пройти цепочку фильтров (или, возможно, другую), прежде чем попадет в сервлет, который собирается с ним работать. Проблема заключается в том, что некоторые действия фильтра безопасности должны выполняться только один раз для запроса. Отсюда необходимость этого фильтра.

Ответ 2

Чтобы понять роль OncePerRequestFilter, нам нужно сначала четко понять, как ведет себя обычный фильтр. Когда вы хотите, чтобы какой-то конкретный код выполнялся непосредственно перед или после выполнения сервлета, вы создаете фильтр, который работает как:

code1   ===>   servlet execution (using chain.doFilter())   ===>    code2

Таким образом, code1 выполняется перед сервлетом и code2 после выполнения сервлета. Но здесь, при выполнении сервлета, может быть другой запрос к другому сервлету, и этот другой сервлет также имеет этот же фильтр. В этом случае этот фильтр будет выполнен снова.

OncePerRequestFilter предотвращает это поведение. Для нашего одного запроса этот фильтр будет выполнен ровно один раз (не больше, не меньше). Такое поведение очень полезно при работе с аутентификацией безопасности.

Ответ 3

  При каких обстоятельствах фильтр может выполняться несколько раз за запрос?


Фильтр может быть вызван как часть запросов REQUEST или ASYNC, которые происходят в отдельных потоках. Мы должны использовать OncePerRequestFilter, так как мы выполняем вызов базы данных для получения принципала или аутентифицированного пользователя, нет смысла делать это более одного раза. После этого мы устанавливаем принципала в контексте безопасности.

Authentication auth = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);

где jwtTokenProvider - это ваш сервис для получения аутентификации из токена jwt.