Как я могу подавить диалог проверки подлинности браузера?
В моем веб-приложении есть страница входа, которая отправляет учетные данные аутентификации через вызов 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.
Ответ 9
Я был в той же самой проблеме и нашел эту ссылку в комментарии здесь, в stackoverflow (не в моем блоге):
http://loudvchar.blogspot.ca/2010/11/avoiding-browser-popup-for-401.html
Надеюсь, это поможет вам.
Ответ 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)
}
}
Я надеюсь, что это поможет кому-то!