Обработка перенаправлений SAML в запросах AJAX

У меня есть несколько приложений AngularJS, использующих Spring/Java и SAML 2.0 для единого входа (используя расширение Spring Security SAML). Мой поставщик SSO-идентификаторов - OpenAM, и все работает довольно хорошо. Однако я сталкиваюсь с ситуацией, когда пользователь выполняет глобальный выход из одного приложения, но открывает другие вкладки. Так как это одностраничные веб-приложения, многие функции по-прежнему могут быть использованы на потерянных вкладках до тех пор, пока пользователь не сделает что-то для вызова ajax-запроса. Конечно, эти AJAX-запросы перехватываются фильтрами SAML Spring Security и запускают попытку аутентификации через REDIRECT на URL-адрес входа OpenAM. Конечно, это приводит к хаосу в браузере, так как перенаправления на другой домен не разрешены по запросам AJAX. Более того, я ничего не могу поделать с $http-перехватчиками Angular, так как запросы "отменены" и информация о качестве недоступна в функции обратного вызова $http (например, удобный код состояния 401/403). Все, что я знаю, это то, что запрос не прошел.

Я не хочу предполагать, что все плохие запросы $http происходят из-за проблем с аутентификацией (и делают $window.location.reload()), так как могут быть законные причины сбоя. Я предпочитаю подавлять перенаправление Spring Security (на страницу входа в OpenAM) для запросов ajax и вместо этого отправлять обратно код состояния 401/403. Это позволило бы мне обработать ошибку в перехватчике $http и выполнить полную загрузку страницы, если это ошибка аутентификации, таким образом, элегантно перенаправляя на страницу входа, как если бы они впервые заходили на сайт.

Есть идеи, как этого добиться?

1 ответ

Решение

Компонент, ответственный за инициализацию аутентификации и решение возвратить ошибку HTTP, выполнить перенаправление,... является экземпляром AuthenticationEntryPoint, Чтобы изменить его поведение, вы можете:

  • настроить текущий SAMLEntryPoint (расширить commence метод) и переопределить поведение по умолчанию в случае, если запрос является вызовом AJAX из Angular, поэтому он возвращает ошибку HTTP вместо выполнения перенаправления в IDP
  • или определить другой security:http элемент в контексте Spring (до текущего), который охватывает только ваши запросы AJAX (например, с атрибутом pattern="/api/**") и использует точку входа, которая ведет себя так, как вы хотите (см. Http403ForbiddenEntryPoint)

Относительно возможной реализации первой пули Владимира - взято из https://www.jasha.eu/blogposts/2015/10/saml-authentication-angularjs-spring-security.html

public class XhrSamlEntryPoint extends SAMLEntryPoint {

  @Override
  public void commence(HttpServletRequest request, HttpServletResponse response,
                       AuthenticationException e) throws IOException, ServletException {
    if (isXmlHttpRequest(request) && e instanceof InsufficientAuthenticationException) {
      response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
      return;
    }
    super.commence(request, response, e);
  }

  private boolean isXmlHttpRequest(HttpServletRequest request) {
    return "XMLHttpRequest".equalsIgnoreCase(request.getHeader("X-Requested-With"));
  }
}

Имейте в виду, что X-Requested-With не является обязательным заголовком, поэтому в соответствии с этим ответом обнаружение не является пуленепробиваемым. В моем случае, поскольку серверная часть использовалась с интерфейсом SPA, я полностью удалил проверку вызова ajax.

Другие вопросы по тегам