Как запретить браузеру вызывать всплывающее окно аутентификации и обрабатывать ошибку 401 с помощью Jquery? - PullRequest
96 голосов
/ 25 марта 2012

Мне нужно отправить запрос авторизации, используя базовую авторизацию.Я успешно реализовал это с помощью jquery.Однако, когда я получаю сообщение об ошибке 401, открывается основное окно браузера auth и не вызывается обратный вызов jquery ajax.

Ответы [ 11 ]

41 голосов
/ 26 марта 2012

Я тоже недавно столкнулся с этой проблемой.Поскольку вы не можете изменить поведение браузера по умолчанию при отображении всплывающего окна в случае 401 ( basic или digest аутентификации), существует два способа это исправить:

  • Измените ответ сервера, чтобы он не возвращал 401.Вместо этого верните код 200 и обработайте его в своем клиенте jQuery.
  • Измените метод, который вы используете для авторизации, на пользовательское значение в вашем заголовке.Браузеры отобразят всплывающее окно для Basic и Digest .Вы должны изменить это как на клиенте, так и на сервере.

    headers : {
      "Authorization" : "BasicCustom"
    }
    

Пожалуйста, взгляните также на this для примера использования jQuery с Basic Auth.

31 голосов
/ 04 июля 2013

Возвращает общий код состояния 400, а затем обрабатывает эту клиентскую сторону.

Или вы можете оставить 401 и не возвращать заголовок WWW-Authenticate, на который действительно реагирует браузер с помощью всплывающего окна аутентификации. Если заголовок WWW-Authenticate отсутствует, браузер не запрашивает учетные данные.

17 голосов
/ 06 октября 2014

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

https://username:password@example.com/admin/...

Если вы получите ошибку 401 (неверное имя пользователя или пароль), она будет корректно обработана с помощью обратного вызова jquery error. Это может вызвать некоторые проблемы с безопасностью (в случае протокола http вместо https), но это работает.

UPD: Поддержка этого решения будет удалена в Chrome 59

10 голосов
/ 20 июня 2016

Как уже отмечали другие, единственный способ изменить поведение браузера - убедиться, что ответ не содержит код состояния 401 или, если он есть, не содержит заголовок WWW-Authenticate: Basic. Поскольку изменение кода состояния не очень семантическое и нежелательное, хорошим подходом является удаление заголовка WWW-Authenticate. Если вы не можете или не хотите изменять приложение веб-сервера, вы всегда можете обслужить его или прокси через Apache (если вы еще не используете Apache).

Вот конфигурация для Apache, чтобы переписать ответ для удаления заголовка WWW-Authenticate. IFF, содержащийся в запросе, содержит заголовок X-Requested-With: XMLHttpRequest (который устанавливается по умолчанию основными платформами Javascript, такими как JQuery / AngularJS и т. Д. ) И ответ содержит заголовок WWW-Authenticate: Basic.

Проверено на Apache 2.4 (не уверен, работает ли он с 2.2). Это зависит от установленного модуля mod_headers. (В Debian / Ubuntu sudo a2enmod headers и перезапустите Apache)

    <Location />
            # Make sure that if it is an XHR request,
            # we don't send back basic authentication header.
            # This is to prevent the browser from displaying a basic auth login dialog.
            Header unset WWW-Authenticate "expr=req('X-Requested-With') == 'XMLHttpRequest' && resp('WWW-Authenticate') =~ /^Basic/"
    </Location>   
5 голосов
/ 06 апреля 2014

Если вы используете сервер IIS, вы можете настроить перезапись URL IIS (v2), чтобы перезаписать заголовок WWW-Authentication в None на запрошенном URL.

Путеводитель здесь .

Значение, которое вы хотите изменить: response_www_authenticate.

Если вам нужна дополнительная информация, добавьте комментарий, и я опубликую файл web.config.

3 голосов
/ 11 августа 2015

Используйте X-Requested-With: XMLHttpRequest с заголовком вашего запроса. Таким образом, заголовок ответа не будет содержать WWW-Authenticate: Basic.

beforeSend: function (xhr) {
                    xhr.setRequestHeader('Authorization', ("Basic "
                        .concat(btoa(key))));
                    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                },
2 голосов
/ 08 октября 2016

Если заголовок WWW-Authenticate удален, вы не получите кэширование учетных данных и не получите заголовок авторизации в запросе.Это означает, что теперь вам нужно будет вводить учетные данные для каждого нового запроса, который вы генерируете.

2 голосов
/ 20 августа 2012

В качестве альтернативы, если вы можете настроить ответ сервера, вы можете вернуть 403 Запрещено.

Браузер не откроет всплывающее окно аутентификации, и будет вызван обратный вызов jquery.

1 голос
/ 05 декабря 2017

В Safari вы можете использовать синхронные запросы, чтобы браузер не отображал всплывающее окно.Конечно, синхронные запросы должны использоваться только в этом случае для проверки учетных данных пользователя ... Вы можете использовать такой запрос перед отправкой фактического запроса, который может вызвать плохой пользовательский опыт, если содержимое (отправленное или полученное) достаточно тяжелое.

    var xmlhttp=new XMLHttpRequest;
    xmlhttp.withCredentials=true;
    xmlhttp.open("POST",<YOUR UR>,false,username,password);
    xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
    xmlhttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
0 голосов
/ 07 июня 2019

С обратной стороны с Spring Boot я использовал пользовательскую BasicAuthenticationEntryPoint:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().and().authorizeRequests()
            ...
            .antMatchers(PUBLIC_AUTH).permitAll()
            .and().httpBasic()
//    https://www.baeldung.com/spring-security-basic-authentication
            .authenticationEntryPoint(authBasicAuthenticationEntryPoint())
            ...

@Bean
public BasicAuthenticationEntryPoint authBasicAuthenticationEntryPoint() {
    return new BasicAuthenticationEntryPoint() {
        {
            setRealmName("pirsApp");
        }

        @Override
        public void commence
                (HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx)
                throws IOException, ServletException {
            if (request.getRequestURI().equals(PUBLIC_AUTH)) {
                response.sendError(HttpStatus.PRECONDITION_FAILED.value(), "Wrong credentials");
            } else {
                super.commence(request, response, authEx);
            }
        }
    };
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...