1. Обзор
В традиционном веб-приложении для входа в систему обычно требуется отправить имя пользователя и пароль на сервер для аутентификации. Хотя эти элементы теоретически могут быть параметрами URL в GET-запросе, очевидно, что гораздо лучше инкапсулировать их в POST-запрос.
Однако должен ли выход из системы быть доступен через запрос GET, поскольку он не требует отправки какой-либо конфиденциальной информации?
В этом уроке мы рассмотрим различные аспекты этого дизайна.
2. Сеансы на стороне сервера
Когда мы управляем сеансами на стороне сервера, мы должны предоставить конечную точку для уничтожения этих сеансов. У нас может возникнуть соблазн использовать метод GET из-за его простоты. Конечно, технически это будет работать, но может привести к нежелательному поведению.
Существуют некоторые процессы, такие как веб-акселераторы , которые предварительно загружают ссылки GET для пользователя. Цель предварительной выборки – немедленное предоставление контента, когда пользователь переходит по этой ссылке, что сокращает время загрузки страницы. Эти процессы предполагают, что ссылка GET предназначена исключительно для возврата содержимого, а не для изменения состояния чего-либо.
Если мы представляем наш выход как запрос GET и представляем его как ссылку, эти процессы могут непреднамеренно выходить из системы пользователей при попытке предварительной выборки ссылок на странице.
Это может не быть проблемой, если наш URL-адрес выхода из системы недоступен статически, например, определяется javascript. Однако в HTTP/1.1 RFC четко указано, что методы GET следует использовать только для возврата содержимого, и пользователь не может нести ответственность за любые побочные эффекты запроса GET. Мы должны следовать этой рекомендации, когда это возможно.
Напротив, RFC описывает метод POST как метод, который может отправлять данные (наш сеанс или идентификатор сеанса) в процесс обработки данных (выход из системы). Это более подходящее описание того, чего мы пытаемся достичь.
2.1. Весенняя безопасность
По умолчанию Spring Security требует, чтобы запрос на выход имел тип POST. Однако мы можем заставить Spring использовать запрос на выход из системы GET, когда мы отключим защиту CSRF :
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
...
}
3. ОТДЫХ без сохранения состояния
Когда мы управляем сеансами REST без сохранения состояния, концепция «выхода из системы» меняется. В среде без сохранения состояния каждый запрос включает весь сеанс. Следовательно, можно «выйти из системы», просто используя Javascript, чтобы сбросить сеанс, а не отправлять какой-либо запрос вообще.
Однако из соображений безопасности сервер все равно должен быть уведомлен о действиях по выходу из системы, чтобы занести отозванный JWT в черный список. Это предотвращает использование сеанса после «выхода из системы».
Даже в среде без сохранения состояния мы все равно должны отправлять запрос на сервер после выхода из системы. Поскольку целью такого запроса не является получение содержимого, его не следует выполнять с помощью GET. Вместо этого сеанс должен быть отправлен POST на сервер с явным намерением выйти из системы.
4. Вывод
В этом кратком обсуждении мы вкратце рассмотрели распространенный вопрос дизайна о том, каким должен быть выход из системы: GET или POST.
Мы рассмотрели различные аспекты этого вопроса:
- Семантически запросы GET не должны иметь побочных эффектов с отслеживанием состояния.
- Существуют процессы, которые пользователи могут запускать в своем браузере и которые включают предварительную загрузку ссылок. Если выход из системы происходит через GET, процесс предварительной выборки может непреднамеренно вывести пользователя из системы после входа в систему.
- Даже сеансы без сохранения состояния должны сообщать серверу о выходе из системы, что должно выполняться с помощью запроса POST.