Как я могу подавить диалог проверки подлинности браузера?

В моем веб-приложении есть страница входа, которая отправляет учетные данные аутентификации через вызов AJAX. Если пользователь вводит правильное имя пользователя и пароль, все в порядке, но если нет, произойдет следующее:

  • Веб-сервер определяет, что хотя запрос содержит хорошо сформированный заголовок авторизации, учетные данные в заголовке не проходят проверку подлинности.
  • Веб-сервер возвращает код состояния 401 и включает один или несколько заголовков WWW-Authenticate, в которых перечислены поддерживаемые типы аутентификации.
  • Браузер обнаруживает, что ответ на мой вызов объекта XMLHttpRequest равен 401, а ответ включает заголовки WWW-Authenticate. Затем он открывает диалоговое окно проверки подлинности, снова запрашивая имя пользователя и пароль.

Все будет хорошо до шага 3. Я не хочу, чтобы диалог всплывал, я хочу, чтобы обработать ответ 401 в моей функции обратного вызова AJAX. (Например, отобразив сообщение об ошибке на странице входа в систему.) Я хочу, чтобы пользователь повторно вводил свое имя пользователя и пароль, но я хочу, чтобы они увидели мою дружескую, заверенную форму входа, а не браузер уродливый, по умолчанию аутентификация.

Кстати, у меня нет контроля над сервером, поэтому, если он возвращает код пользовательского статуса (т.е. что-то, отличное от 401), это не вариант.

Есть ли способ подавить диалог проверки подлинности? В частности, могу ли я подавить диалог проверки подлинности в Firefox 2 или новее? Есть ли способ подавить диалог Connect to [host] в IE 6 и более поздних версиях?


Edit
Дополнительная информация от автора (18 сентября):
Я должен добавить, что реальная проблема при открытии диалогового окна проверки подлинности браузера заключается в том, что он предоставляет пользователю недостаточную информацию.

Пользователь только что ввел имя пользователя и пароль через форму на странице входа, он считает, что он набрал их оба правильно, и он нажал кнопку отправки или нажал кнопку ввода. Его ожидание состоит в том, что он будет взят на следующую страницу или, возможно, сказал, что он неверно ввел свою информацию и должен повторить попытку. Тем не менее, ему вместо этого предлагается неожиданное диалоговое окно.

В диалоговом окне не подтверждается тот факт, что он просто вводил имя пользователя и пароль. В нем четко не указано, что есть проблема и что он должен попробовать еще раз. Вместо этого диалоговое окно предоставляет пользователю криптографическую информацию, например "Сайт говорит:" [realm] ". Где [царство] - это короткое царство, которое может любить только программист.

Разработчики веб-браузеров отмечают: никто не спрашивал, как подавить диалог проверки подлинности, если сам диалог был просто более удобным для пользователя. Вся причина, по которой я делаю регистрационную форму, заключается в том, что наша команда управления продуктами правильно считает, что диалоговые окна проверки браузеров ужасны.

Ответ 1

Я не думаю, что это возможно - если вы используете реализацию HTTP-клиента браузера, он всегда будет всплывать в этом диалоговом окне. Приходят на ум два взлома:

  • Возможно, Flash обрабатывает это по-другому (я еще не пробовал), поэтому наличие флеш-ролика может помочь запросу.

  • Вы можете настроить "прокси" для службы, к которой вы обращаетесь на своем собственном сервере, и немного изменить заголовки аутентификации, чтобы браузер не узнал их.

Ответ 2

Здесь я столкнулся с той же проблемой, и инженер-бэкэнд в моей компании реализовал поведение, которое, по-видимому, считается хорошей практикой: когда вызов URL-адреса возвращает 401, если клиент установил заголовок X-Requested-With: XMLHttpRequest, сервер отбрасывает заголовок www-authenticate в своем ответе.

Побочным эффектом является то, что всплывающее сообщение по умолчанию не появляется.

Убедитесь, что ваш вызов API имеет заголовок X-Requested-With, установленный на XMLHttpRequest. Если это так, вам нечего делать, кроме изменения поведения сервера в соответствии с этой хорошей практикой...

Ответ 3

Браузер выдает приглашение для входа в систему, если выполняются оба следующих условия:

  • Статус HTTP - 4xx Заголовок
  • WWW-Authenticate присутствует в ответе

Если вы можете контролировать HTTP-ответ, вы можете удалить заголовок WWW-Authenticate из ответа, и браузер не отобразит диалоговое окно входа.

Если вы не можете контролировать ответ, вы можете настроить прокси, чтобы отфильтровать заголовок WWW-Authenticate из ответа.

Насколько я знаю (не стесняйтесь исправлять меня, если я ошибаюсь), нет способа предотвратить приглашение для входа в систему после того, как браузер получит заголовок WWW-Authenticate.

Ответ 4

В Mozilla вы можете достичь этого со следующим script при создании объекта XMLHttpRequest:

xmlHttp=new XMLHttpRequest();
xmlHttp.mozBackgroundRequest = true;
xmlHttp.open("GET",URL,true,USERNAME,PASSWORD);
xmlHttp.send(null);

Вторая строка предотвращает диалоговое окно....

Ответ 5

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

Если у вас есть доступ к коду для веб-службы, которая возвращает 401. Просто измените службу, чтобы вернуть 403 (Forbidden) в этой ситуации вместо 401. Браузер не будет запрашивать учетные данные в ответ на 403. 403 - это правильный код для аутентифицированного пользователя, который не авторизован для определенного ресурса. Кажется, что ситуация в OP.

Из документа IETF на странице 403:

Сервер, который получает действительные учетные данные, которые не соответствуют  доступ для доступа должен отвечать кодом статуса 403 (Запрещенный)

Ответ 6

Какие серверные технологии вы используете и есть ли определенный продукт, который вы используете для аутентификации?

Поскольку браузер выполняет только свою работу, я считаю, что вам нужно изменить ситуацию на стороне сервера, чтобы не вернуть код состояния 401. Это можно сделать с помощью настраиваемых форм аутентификации, которые просто возвращают форму снова, когда аутентификация завершается с ошибкой.

Ответ 7

В Mozilla land, устанавливая параметр mozBackgroundRequest XMLHttpRequest (docs), чтобы true подавлял эти диалоги и заставлял запросы просто терпеть неудачу. Тем не менее, я не знаю, насколько хороша поддержка кросс-браузера (в том числе ли качество информации об ошибках в этих неудачных запросах очень хорошо в браузерах.)

Ответ 8

jan.vdbergh имеет правду, если вы можете изменить 401 на стороне сервера для другого кода состояния, браузер не поймает и не откроет всплывающее окно. Другим решением может быть изменение заголовка WWW-Authenticate для другого настраиваемого заголовка. Я не верю, почему другой браузер не может его поддерживать, в нескольких версиях Firefox мы можем выполнить запрос xhr с помощью mozBackgroundRequest, но в других браузерах?? здесь есть интересная ссылка с этой проблемой в Chromium.

Ответ 10

У меня есть эта же проблема с MVC 5 и VPN, где, когда мы находимся за пределами DMZ с использованием VPN, нам приходится отвечать на это сообщение в браузере. Использование .net Я просто обрабатываю маршрутизацию ошибки, используя

<customErrors defaultRedirect="~/Error"  >
  <error statusCode="401" redirect="~/Index"/>
</customErrors>

до сих пор он работал, потому что действие индекса под домашним контроллером проверяет пользователя. Представление в этом действии, если вход в систему не увенчался успехом, имеет элементы управления доступом, которые я использую для регистрации пользователя при использовании с использованием запроса LDAP, переданного в службы каталогов:

      DirectoryEntry entry = new DirectoryEntry("LDAP://OurDomain");
      DirectorySearcher Dsearch = new DirectorySearcher(entry);
      Dsearch.Filter = "(SAMAccountName=" + UserID + ")";
      Dsearch.PropertiesToLoad.Add("cn");

Пока это работает до сих пор, и я должен сообщить вам, что я все еще тестирую его, и у вышеуказанного кода нет причин для запуска, поэтому он подвергается удалению... В настоящее время тестирование включает попытку обнаружить случай, когда второй набор кода более полезен. Опять же, это незавершенное производство, но поскольку это может помочь вам или задуматься над некоторыми идеями, я решил добавить его сейчас... Я обновлю его с окончательными результатами, как только все тестирование будет выполнено.

Ответ 11

Для тех, кто не поддерживает С# здесь ActionAttribute, который возвращает 400 вместо 401 и "проглатывает" Basic auth dialog.

public class NoBasicAuthDialogAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        base.HandleUnauthorizedRequest(filterContext);
        filterContext.Result = new HttpStatusCodeResult(400);
    }
}

используйте, как показано ниже:

[NoBasicAuthDialogAuthorize(Roles = "A-Team")]
public ActionResult CarType()
{
 // your code goes here
}

Надеюсь, это сэкономит вам некоторое время.

Ответ 12

Я использую Node, Express и Passport и борюсь с той же проблемой. Я получил его для работы, явно установив заголовок www-authenticate в пустую строку. В моем случае это выглядело так:

(err, req, res, next) => {
  if (err) {
    res._headers['www-authenticate'] = ''
    return res.json(err)
  }
}

Я надеюсь, что это поможет кому-то!