Повторный вызов на истекший сеанс: ответ HTTP 401 заставляет браузер отображать окно входа в систему
Я написал приложение HTML 5, которое использует AngularJS и интерфейсы с бэкэндом Java REST, работающим на Tomcat.
Я использую Spring Security для обработки логина и безопасности.
Когда пользователь вводит веб-сайт, он пересылается на страницу входа в систему, которая создает сеанс и перенаправляется на индексную страницу. REST вызывает загрузку дополнительных данных с сервера, а затем использует этот сеанс для аутентификации.
Если сеанс отсутствует, я возвращаюсь к базовой аутентификации по HTTP, так что можно вызывать конечные точки REST отдельно от веб-приложения.
Проблема, с которой я столкнулся, - это время окончания сеанса. Это вызывает ответ HTTP 401 Unauthenticated
с сервера. Я думал, что смогу поймать эту ошибку и перенаправить пользователя обратно на страницу входа с Javascript. Однако до того, как вызывается мой обработчик ошибок, браузер сначала показывает окно входа в систему, только если я нажму "Отменить мой обработчик ошибок Javascript", вы сможете обработать ответ.
Мой вопрос в том, есть ли способ предотвратить отображение браузером этого окна входа в систему? Или это общая проблема с моим дизайном приложения?
Альтернативой может быть не использование сеанса вообще и кэширование имени пользователя и пароля в приложении. Затем мне нужно отправить его с каждым вызовом REST с использованием базовой аутентификации, будет ли это лучший подход?
Ниже приведен ответ HTTP с сервера:
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
WWW-Authenticate: Basic realm="Spring Security Application"
Content-Type: text/html;charset=utf-8
Content-Length: 999
Date: Mon, 30 Sep 2013 11:00:34 GMT
Обновление: Похоже, что причиной этого является заголовок WWW-Authenticate
, который заставляет браузер отображать диалоговое окно входа в систему.
Ответы
Ответ 1
Наконец, я нашел решение для этого. Как я упоминал в своем обновлении, причина в том, что ответ содержит поле заголовка WWW-Authenticate
. Моим решением было изменить конфигурацию безопасности spring, чтобы вернуть другой заголовок:
WWW-Authenticate: FormBased
Для этого мне пришлось реализовать интерфейс AuthenticaitonEntryPoint
и вручную задать заголовок и код состояния в ответе:
@Component( "restAuthenticationEntryPoint" )
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence( HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException ) throws IOException {
response.setHeader("WWW-Authenticate", "FormBased");
response.setStatus( HttpServletResponse.SC_UNAUTHORIZED );
}
}
то я изменил конфигурацию spring -security и установил entry-point-ref
для указания на новый класс:
<http pattern="/rest/**" create-session="never" entry-point-ref="restAuthenticationEntryPoint">
<intercept-url pattern="/rest/**" access="ROLE_USER" />
<http-basic />
<session-management />
</http>
Ответ 2
Если вы хотите избежать изменения сервера и заставить его возвращать заголовок WWW-Authenticate
для всех других вызывающих абонентов, вы можете изменить свой клиент для отправки своего запроса с заголовком X-Requested-With
с XMLHttpRequest
значением.
По умолчанию Spring Security не отправит WWW-Authenticate
для таких запросов. (см. Spring источник)