Як я можу придушити діалогове вікно автентифікації браузера?


85

У моїй веб-програмі є сторінка входу, яка подає дані автентифікації за допомогою виклику AJAX. Якщо користувач вводить правильні ім’я користувача та пароль, все в порядку, але якщо ні, трапляється таке:

  1. Веб-сервер визначає, що, хоча запит включав добре сформований заголовок авторизації, облікові дані в заголовку не успішно аутентифікуються.
  2. Веб-сервер повертає код стану 401 і включає один або кілька заголовків автентифікації WWW із переліком підтримуваних типів автентифікації.
  3. Браузер виявляє, що відповідь на мій виклик об’єкта XMLHttpRequest - це 401, і відповідь включає заголовки WWW-Authenticate. Потім з’являється діалогове вікно автентифікації з проханням ввести ім’я користувача та пароль.

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

До речі, я не маю ніякого контролю над сервером, тому повернення користувацького коду стану (тобто щось інше, ніж 401) не є варіантом.

Чи є спосіб заблокувати діалогове вікно автентифікації? Зокрема, чи можу я вимкнути діалогове вікно «Необхідна автентифікація» у Firefox 2 або пізнішої версії? Чи є спосіб заблокувати діалогове вікно Підключення до [хосту] в IE 6 та пізніших версіях?


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

Користувач щойно ввів ім’я користувача та пароль через форму на сторінці входу, він вважає, що ввів їх обидва правильно, і натиснув кнопку подати або натиснув Enter. Він сподівається, що його переведуть на наступну сторінку або, можливо, скажуть, що він ввів свою інформацію неправильно, і йому слід спробувати ще раз. Однак натомість перед ним з’являється несподіване діалогове вікно.

Діалог не має ніякого підтвердження того факту , що він просто зробив ввести ім'я користувача і пароль. У ньому чітко не вказано, що виникла проблема, і що йому слід спробувати ще раз. Натомість діалогове вікно надає користувачеві загадкову інформацію на зразок "Сайт каже:" [сфера] ". Де [царство] - це коротка назва сфери, яку любив би лише програміст.

Дизайнери веб-браузерів беруть до уваги: ​​ніхто не запитає, як придушити діалогове вікно автентифікації, якби саме діалогове вікно було просто більш зручним для користувача. Вся причина того, що я роблю форму для входу в тому , що наша команда управління продуктом справедливо вважає Діалоги аутентифікації браузерів буде жахливо.


1
Відповідь полягає в тому, що хорошої відповіді немає. Хакери, запропоновані Marijn, настільки близькі, наскільки це можливо. Звичайно, використання спеціальної автентифікації, зрозумілої для сервера та вашого JavaScript, але не для браузера, також зробить трюк, якщо це можливо.
dgvid

Я був у тій же проблемі і знайшов це посилання в коментарі тут щодо stackoverflow (не мого блогу): loudvchar.blogspot.ca/2010/11/… Сподіваюся, це допоможе вам.
gies0r

Відповіді:


17

Я не думаю, що це можливо - якщо ви використовуєте реалізацію HTTP-клієнта браузера, це діалогове вікно завжди з’явиться. Пам’ятаються два хаки:

  1. Можливо, Flash обробляє це по-іншому (я ще не пробував), тому, якщо запит на флеш-фільм зробить запит, це може допомогти.

  2. Ви можете встановити "проксі" для послуги, до якої ви отримуєте доступ на власному сервері, і попросити її трохи змінити заголовки автентифікації, щоб браузер їх не розпізнавав.


"Неможливо", здається, правильна відповідь, хоча я підозрюю, що хак "проксі" зробив би трюк.
dgvid

@Stobor Прийнята відповідь на дублікат, який ви розмістили, насправді посилається на це питання як його відповідь!
8bitjunkie

3
@ 7SpecialGems Хороший улов. Я не припускав, що це обман, я прив’язав до конкретної відповіді (WWW-Authenticate), яка була розміщена через 4 роки після прийнятої відповіді. Не дивлячись на минуле, я не пам’ятаю, чому я на це дивився чи як тестував.
Stobor

1
Я намагаюся виявити несанкціоновану помилку 401 за цим кодом: $ .ajaxSetup ({statusCode: {401: function () {RedirectToLogin ();}}}); Але IE завжди відображає діалогове вікно автентифікації браузера. Як я можу придушити це діалогове вікно в ASP.Net MVC 2?
PaulP

@PaulP, як вже було сказано, вам потрібен проксі-сервер, який видалить відповіді коду стану 401 їх заголовка WWW-Authenticate або якусь реалізацію користувацького сервера.
Motes

51

Я зіткнувся з тією ж проблемою тут, і бекенд-інженер у моїй компанії застосував поведінку, яка, мабуть, вважається гарною практикою: коли виклик URL-адреси повертає 401, якщо клієнт встановив заголовок X-Requested-With: XMLHttpRequest, сервер скидає www-authenticateзаголовок у свій відповідь.

Побічним ефектом є те, що спливаюче вікно автентифікації за замовчуванням не відображається.

Переконайтеся, що для вашого дзвінка API встановлено X-Requested-Withзаголовок XMLHttpRequest. Якщо так, то нічого не робити, крім зміни поведінки сервера відповідно до цієї належної практики ...


3
Якщо серверний сервер заснований на Java / Spring, DelegatingAuthenticationEntryPointця поведінка обробляється за вас.
Дерек Слайф

Дякую за це. Багато бібліотек прийняли таку поведінку, включаючи
Devise

1
будь-яка ідея, як це зробити в nginx? "коли виклик до URL-адреси повертає 401, якщо клієнт встановив заголовок X-Request-With: XMLHttpRequest, сервер скидає заголовок www-authenticate у своїй відповіді."
markmnl

18

Браузер вискакує запит на вхід, коли виконуються обидві наведені нижче умови:

  1. Статус HTTP - 4xx
  2. WWW-Authenticate Заголовок присутній у відповіді

Якщо ви можете контролювати відповідь HTTP, тоді ви можете видалити WWW-Authenticateзаголовок із відповіді, і браузер не відкриє діалогове вікно входу.

Якщо ви не можете контролювати відповідь, ви можете встановити проксі-сервер, щоб відфільтрувати WWW-Authenticateзаголовок із відповіді.

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


Хороша інформація. Що стосується допустимих WWW-Authenticateзначень заголовків см stackoverflow.com/a/1748451/225217
Brice Roncace

6

Я усвідомлюю, що це питання та відповіді на нього дуже давні. Але я опинився тут. Можливо, це зроблять і інші.

Якщо у вас є доступ до коду веб-служби, яка повертає 401. Просто змініть службу, щоб повернути 403 (Заборонено) у цій ситуації замість 401. Браузер не запитуватиме облікові дані у відповідь на 403. 403 є правильний код для автентифікованого користувача, який не авторизований для певного ресурсу. Що здається ситуацією з ОП.

З документа IETF від 403:

Сервер, який отримує дійсні облікові дані, які не є достатніми для отримання доступу, повинен відповісти кодом стану 403 (Заборонено)


4

У Mozilla ви можете досягти цього за допомогою наступного сценарію під час створення об'єкта XMLHttpRequest:

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

Другий рядок перешкоджає діалоговому вікні ....


1
Здається, це нічого не робить під Firefox 2. Це призводить до помилки безпеки DOM, NS_ERROR_DOM_SECURITY_ERR код 1000, під Firefox 3.
dgvid

2

Яку серверну технологію ви використовуєте і чи існує конкретний продукт, який ви використовуєте для автентифікації?

Оскільки браузер виконує лише свою роботу, я вважаю, що вам доведеться змінити ситуацію на стороні сервера, щоб не повертати код стану 401. Це можна зробити за допомогою спеціальних форм автентифікації, які просто повертають форму знову, коли автентифікація не вдається.


2

У Mozilla land встановлення параметра mozBackgroundRequest для XMLHttpRequest ( docs ) на true пригнічує ці діалоги та спричиняє простий збій запитів. Однак я не знаю, наскільки хороша підтримка між браузерами (включаючи те, чи дуже висока якість інформації про помилки в цих невдалих запитах у всіх браузерах).


Префікс moz не передбачає підтримки між браузерами (якщо ви не можете знайти подібні параметри, які працюють у кожному з інших браузерів).
Brilliand

2

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


1

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

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

до цього часу це спрацювало, оскільки дія Index під контролером будинку перевіряє користувача. Представлення даних у цій дії, якщо вхід не вдався, містить елементи керування входом, які я використовую для входу користувача за допомогою запиту LDAP, переданого до служб каталогів:

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

Хоча це працювало дотепер, і я повинен повідомити вам, що я все ще тестую його, і наведений вище код не мав жодної причини для запуску, тому він підлягає видаленню ... тестування наразі включає спробу виявити випадок, коли другий набір коду більше не використовується. Знову ж таки, це незавершена робота, але оскільки це може допомогти або розігнати мозок для якихось ідей, я вирішив додати це зараз ... Я оновлю його з кінцевими результатами, коли все тестування буде зроблено.


1

Я використовую Node, Express & Passport і боровся з тією ж проблемою. Я змусив це працювати, явно встановивши www-authenticateзаголовок на порожній рядок. У моєму випадку це виглядало так:

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

Сподіваюся, це комусь допомагає!


0

Для тих, хто скасовує C #, ось, ActionAttributeщо повертається 400замість 401, і "ковтає" базове діалогове вікно автентифікації.

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
}

Сподіваюся, це заощадить ваш час.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.