Мені потрібно надіслати запит на авторизацію, використовуючи базовий auth. Я успішно реалізував це за допомогою jquery. Однак, коли я отримую помилку 401, відкривається спливаюче вікно браузера auth, і зворотний виклик jquery ajax не викликається.
Мені потрібно надіслати запит на авторизацію, використовуючи базовий auth. Я успішно реалізував це за допомогою jquery. Однак, коли я отримую помилку 401, відкривається спливаюче вікно браузера auth, і зворотний виклик jquery ajax не викликається.
Відповіді:
З цим питанням я стикався і нещодавно. Оскільки ви не можете змінити поведінку браузера за замовчуванням щодо показу спливаючого вікна у разі 401
( основної або дайджест автентифікації), це можна виправити двома способами:
401
. 200
Натомість поверніть код і обробіть це у своєму клієнті jQuery.Змініть метод, який ви використовуєте для авторизації, на спеціальне значення у своєму заголовку. Браузери відображатимуть спливаючі вікна для Basic та Digest . Ви повинні змінити це як на клієнті, так і на сервері.
headers : {
"Authorization" : "BasicCustom"
}
Будь ласка, погляньте на це для прикладу використання jQuery з Basic Auth.
<security:http-basic/>
вам не потрібно визначати, basicAuthenticationFilter
але слід визначати як <security:http-basic entry-point-ref="myBasicAuthenticationEntryPoint"/>
.
401
а, WWW-Authenticate:Bearer WWW-Authenticate:NTLM WWW-Authenticate:Negotiate
чи знаєте ви, чому це було б?
Поверніть загальний код 400 стану, а потім обробіть цей клієнт.
Або ви можете зберегти 401, а не повернути заголовк WWW-Authenticate, що насправді відповідає браузеру при спливаючому вікні аутентифікації. Якщо заголовок WWW-Authenticate відсутній, браузер не вимагатиме отримання облікових даних.
res.removeHeader('www-authenticate'); // prevents browser from popping up a basic auth window.
Ви можете придушити основне спливаюче вікно аутентифікації з таким URL-адресом запиту:
https://username:password@example.com/admin/...
Якщо ви отримаєте помилку 401 (неправильне ім’я користувача або пароль), вона буде правильно оброблена зворотним зв'язком jquery error. Це може спричинити деякі проблеми із безпекою (у випадку протоколу http замість https), але це працює.
UPD: Підтримка цього рішення буде видалена в Chrome 59
https://user:pass@host/
в M59, приблизно в червні 2017 року. Докладнішу інформацію див. У цьому блозі щодо хростату .
Як зазначали інші, єдиний спосіб змінити поведінку браузера - переконатися, що відповідь або не містить код стану 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>
proxy_hide_header WWW-Authenticate;
Використовуйте X-Requested-With: XMLHttpRequest із заголовком запиту. Тож заголовок відповіді не буде містити WWW-Authenticate: Basic.
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', ("Basic "
.concat(btoa(key))));
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
},
Якщо ви використовуєте сервер IIS, можна налаштувати IIS URL Переписуючи (v2) , щоб переписати WWW-Authentication
заголовок None
на запитаний URL.
Значення, яке ви хочете змінити response_www_authenticate
.
Якщо вам потрібна додаткова інформація, додайте коментар, і я опублікую файл web.config.
Якщо заголовок WWW-Authenticate видалено, ви не отримаєте кешування облікових даних і не зможете повернути заголовок авторизації у запиті. Це означає, що тепер вам доведеться вводити облікові дані для кожного нового генерованого вами запиту.
Крім того, якщо ви можете налаштувати відповідь вашого сервера, ви можете повернути 403 Заборонено.
Браузер не відкриє спливаюче вікно аутентифікації, і буде викликано зворотний дзвінок jquery.
У 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');
Створіть URL / login, ніж приймайте параметри "user" та "password" через GET і не вимагайте базових auth. Тут використовуйте php, node, java, що завгодно і проаналізуйте ваш passwd файл та порівняйте параметри (user / pass) проти нього. Якщо є відповідність, перенаправляйте на http: // user: pass@domain.com/ (якщо це встановить обліковий запис у вашому браузері), якщо ні, надішліть відповідь 401 (без заголовка WWW-Authenticate).
Зі зворотного боку за допомогою 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);
}
}
};
}