Код ответа 401, инициирующий базовую аутентификацию перед обработчиком ошибок jquery ajax

У меня есть сценарий, когда мне приходится обрабатывать аутентификацию запросов ajax, используя "Аутентификация форм". Основываясь на некоторых поисках и помощи из моего предыдущего сообщения stackoverflow, я решил использовать метод, описанный в здесь.

Идея состоит в том, чтобы отправить ответ 401 для неавторизованных запросов, а затем обработать это в обработчике ошибок AJAX. Таким образом, у меня есть обработчик ошибок AJAX на моей странице ASP.NET MVC3 Layout, который перенаправляет браузер на страницу входа, когда он получает ответ 401 на запросы без аутентификации ajax. Вот обработчик ошибок ajax.

$(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) {
    if (jqXHR.status == "401") {
        window.location.replace(loginUrl);
    }
    ....
});

Все это хорошо работает на моем локальном сервере IIS 7.5. Но на сервере, где размещен мой сайт, к сожалению, я получаю базовое всплывающее всплывающее окно по неаутентифицированным запросам ajax (например, время ожидания сеанса), до того, как обработчик ошибок AJAX запускается и перенаправляет браузер на страницу входа. Когда я отменяю всплывающее окно "Authentication Required", нажимая кнопку "Отмена", затем запускается обработчик ошибок AJAX, и я перенаправляется на страницу входа.

Итак, почему браузер показывает всплывающее окно аутентификации перед запуском обработчика ошибок AJAX?

Изменить: Сервер хостинга работает с IIS 6.

Ответ 1

как Softlion сказал

Это простой вопрос с легким ответом. 401 преобразуется в страницу авторизации > 302 на страницу входa > с помощью модуля авторизации .net. Браузер никогда не видит 401 только 302.

если вы используете .net 4 и более поздние версии, вы используете код ниже

HttpContext.Response.SuppressFormsAuthenticationRedirect = true;

он отлично работает для меня.

Ответ 2

Это простой вопрос с легким ответом. 401 преобразуется в 302 на страницу входа с помощью модуля авторизации .net. Браузер никогда не видит 401 только 302.

Конечно, это не очень хорошо работает с вызовами ajax.

Лучшее решение, которое я попробовал, и я в настоящее время использую, требует записи нового атрибута, который ловит 401 и преобразует его в... 409, который улавливается обработчиком jQuery ajax.

Это часть платного продукта, поэтому я не могу дать никакого кода.

Ответ 3

Попробуйте удалить заголовок WWW-Authenticate из ответа.

Ответ 4

IIS 6 в интегрированном режиме? Я не думаю, что есть такая вещь, если вы не говорите об интегрированной аутентификации.

Я предполагаю, что вы используете расширение без aspx, поэтому на IIS6 это означает, что он даже не попадает в процесс .net. Таким образом, IIS использует собственную страницу ответов об ошибке 401.

Вероятно, решение состоит в том, чтобы заставить все запросы обрабатываться процессом .net.

Ваш хост должен будет перейти в свойства IIS > конфигурации > сопоставления подстановочных знаков - и сопоставить все с процессом .net.

Ответ 5

.net не поймает ошибки 401. Я сделал, чтобы установить страницу с ошибкой IIS со страницы 401 по умолчанию на мою собственную статическую страницу 401. С этой страницы я использовал javascript для перенаправления на другой обработчик.

Ответ 6

Решение здесь заключается в написании пользовательского HttpModule для обхода поведения по умолчанию MVC. Как только я наконец смог зарегистрировать модуль (приветствует Дэвида Эббо), это сработало для меня. Вы можете выбрать свои собственные критерии для вызова SuppressAuthenticationRedirect.

public class SuppressFormsAuthenticationRedirectModule : IHttpModule {
  private static readonly object SuppressAuthenticationKey = new Object();

  public static void SuppressAuthenticationRedirect(HttpContext context) {
    context.Items[SuppressAuthenticationKey] = true;
  }

  public static void SuppressAuthenticationRedirect(HttpContextBase context) {
    context.Items[SuppressAuthenticationKey] = true;
  }

  public void Init(HttpApplication context) {
    context.PostReleaseRequestState += OnPostReleaseRequestState;
    context.EndRequest += OnEndRequest;
  }

  private void OnPostReleaseRequestState(object source, EventArgs args) {
    var context = (HttpApplication)source;
    var response = context.Response;
    var request = context.Request;

    if (response.StatusCode == 401 && request.Headers["X-Requested-With"] == 
      "XMLHttpRequest") {
      SuppressAuthenticationRedirect(context.Context);
    }
  }

  private void OnEndRequest(object source, EventArgs args) {
    var context = (HttpApplication)source;
    var response = context.Response;

    if (context.Context.Items.Contains(SuppressAuthenticationKey)) {
      response.TrySkipIisCustomErrors = true;
      response.ClearContent();
      response.StatusCode = 401;
      response.RedirectLocation = null;
    }
  }

  public void Dispose() {
  }

  public static void Register() {
    DynamicModuleUtility.RegisterModule(
      typeof(SuppressFormsAuthenticationRedirectModule));
  }
}

Ответ 7

Для меня это оказалось простым. Большинство веб-сайтов IIS с анонимной аутентификацией также имеют включенную службу Windows Auth по умолчанию

Конфигурация аутентификации

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

<security> <authentication> <anonymousAuthentication enabled="true" /> <windowsAuthentication enabled="false" /> </authentication> </security>

Ответ 8

Подождите! Я думал, вы сказали запрос Ajax, как вы можете получить всплывающее окно по запросу ajax? Я уверен, что в другом месте вы вызываете вызов URL еще до вызова AJAX. Из вашего сценария было доказано, что при отмене всплывающего окна выполняется ваш фактический запрос ajax и, следовательно, вы можете выполнить перенаправление ajax.

Идея состоит в том, чтобы отправить ответ 401 для неавторизованных запросов, а затем обработать это в обработчике ошибок AJAX

Вы можете получить ответ ajax, только если вы отправляете запрос ajax, если вы отправляете обычный HTTP-запрос, тогда вы получите всплывающее окно. Это не имеет ничего общего с .Net или Java:)