Використовуйте базову автентифікацію за допомогою jQuery та Ajax


419

Я намагаюся створити базову автентифікацію через браузер, але я не можу дійсно дістатися туди.

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

Адреса повинна бути приблизно такою:

http://username:password@server.in.local/

У мене є форма:

<form name="cookieform" id="login" method="post">
      <input type="text" name="username" id="username" class="text"/>
      <input type="password" name="password" id="password" class="text"/>
      <input type="submit" name="sub" value="Submit" class="page"/>
</form>

І сценарій:

var username = $("input#username").val();
var password = $("input#password").val();

function make_base_auth(user, password) {
  var tok = user + ':' + password;
  var hash = Base64.encode(tok);
  return "Basic " + hash;
}
$.ajax
  ({
    type: "GET",
    url: "index1.php",
    dataType: 'json',
    async: false,
    data: '{"username": "' + username + '", "password" : "' + password + '"}',
    success: function (){
    alert('Thanks for your comment!');
    }
});

6
Отже, ви не хочете, щоб браузер обробляв автентифікацію BASIC? Чому б просто не використовувати автентифікацію на основі форми?
— no.good.at.coding

@ no.good.at.coding Якщо вам потрібно інтегруватися з стороннім API, що стоїть за аутентифікацією (це те, що я намагаюся зробити - developer.zendesk.com/rest_api/docs/core/… )
— Брайан Ханнай,

Відповіді:


467

Використовуйте beforeSendзворотний дзвінок jQuery, щоб додати заголовок HTTP з інформацією про автентифікацію:

beforeSend: function (xhr) {
    xhr.setRequestHeader ("Authorization", "Basic " + btoa(username + ":" + password));
},

6
я використовую приклад u дав, але він не працює `$ .ajax ({url:" server.in.local / index.php ", beforeSend: function (xhr) {xhr.setRequestHeader (" Авторизація "," Basic " "+ EncodeBase64 (" ім'я користувача: пароль "));}, успішно: функція (val) {// сигнал (val); попередження (" Дякую за ваш коментар! ");}}); `
— Patrioticcow

69
beforeSend: function(xhr) { xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); };працює для мене
— Rico Suter

12
Проблема ... Якщо дані, які я передаю, не вдаються, в Chrome користувачеві відкривається діалогове вікно, щоб знову ввести ім'я користувача / pwd. Як я можу запобігти появі цього 2-го діалогового вікна, якщо облікові дані не вдаються?
— Девід

2
Чи не залишать це ім’я користувача та пароль відкритими для того, щоб хтось бачив? Навіть якщо це в base64, вони можуть просто розшифрувати його. Те саме з відповіддю нижче.
— cbron

6
@calebB Основна автентифікація взагалі просто залишає ім’я користувача та пароль відкритими для того, щоб хтось бачив. Це не лише проблема з описаним тут методом. Якщо використовується базова аутентифікація або справді будь-яка автентифікація, слід також використовувати SSL.
— Джейсон Джексон

354

Як змінюються речі за рік. На додаток до атрибута заголовка замість xhr.setRequestHeaderпоточного jQuery (1.7.2+) включає атрибут імені користувача та пароля з $.ajaxвикликом.

$.ajax
({
  type: "GET",
  url: "index1.php",
  dataType: 'json',
  username: username,
  password: password,
  data: '{ "comment" }',
  success: function (){
    alert('Thanks for your comment!'); 
  }
});

EDIT з коментарів та інших відповідей: Щоб бути зрозумілим - щоб попередньо надсилати автентифікацію без 401 Unauthorizedвідповіді, замість setRequestHeader(попередньо -1.7) використовуйте 'headers':

$.ajax
({
  type: "GET",
  url: "index1.php",
  dataType: 'json',
  headers: {
    "Authorization": "Basic " + btoa(USERNAME + ":" + PASSWORD)
  },
  data: '{ "comment" }',
  success: function (){
    alert('Thanks for your comment!'); 
  }
});

15
Не повинно бути usernameі ні user? Крім того, це зовсім не те саме: з онлайнових докосів і мого досвіду, схоже, це не є преференційним, як цього вимагають деякі API. Іншими словами, він надсилає Authorizationзаголовок лише тоді, коли повернеться код 401.
— Стефано Фратині

3
@StefanoFratini - ви вірні в обох аспектах. Виправлено поле імені користувача, і добре знати про превентивний auth vs відповідати лише на виклик. Визначення заголовка чітко, як і в інших відповідях, дозволить використовувати цей "пасивний" варіант базового авт.
— jmanning2k

для мене вищевказаний варіант не працював, це спрацьовувало як шарм .. дякую
— Anoop Isaac

Дивіться коментар вище, виправте цю відповідь, щоб вказати {"Authorization": "Basic" + btoa ("user: pass")} як правильний заголовок
— Jay

2
Це відповідь, на яку я шукав! Ключовим бітом у цій відповіді для мене є те, як 'заголовок' використовується для попереднього надсилання аутентифікації. На моє запитання тут відповідає це. stackoverflow.com/questions/28404452/…
— Стівен Андерсон

63

Використовуйте зворотний виклик beforeSend, щоб додати заголовок HTTP з інформацією про автентифікацію, наприклад:

var username = $("input#username").val();
var password = $("input#password").val();  

function make_base_auth(user, password) {
  var tok = user + ':' + password;
  var hash = btoa(tok);
  return "Basic " + hash;
}
$.ajax
  ({
    type: "GET",
    url: "index1.php",
    dataType: 'json',
    async: false,
    data: '{}',
    beforeSend: function (xhr){ 
        xhr.setRequestHeader('Authorization', make_base_auth(username, password)); 
    },
    success: function (){
        alert('Thanks for your comment!'); 
    }
});

4
ви повинні помітити, що "btoa", що використовується тут для шифрування Base64, не підтримується у версіях IE менше 10 та в деяких мобільних платформах
— SET

1
також, відповідно до цього розробника.mozilla.org/ en-US/docs/DOM/window.btoa, ви повинні використовувати btoa (unescape (encodeURIComponent (str)))
— SET

@SET, я думаю, що це повинно бути btoa (encodeURIComponent (escape (str)))
— Saurabh Kumar

Я хотів отримати відповідь, тому позбувся асинхронної помилки та додав параметр результату до функції успіху. У мене також був заздалегідь створений заголовок авторизації, тому його просто використовували.
— radtek

1
@SET слід зазначити, що Base64 - це не шифрування, це кодування. Якщо це було шифрування, розшифрувати його за допомогою єдиного виклику функції було б не дуже просто
— Кріс,

40

Або просто використовуйте властивість заголовків, введених у 1.5:

headers: {"Authorization": "Basic xxxx"}

Довідка: jQuery Ajax API


Скажіть, будь ласка, як це зробити для кожного користувача? Я маю на увазі отримати маркер api для кожного користувача із бази даних та надіслати його із заголовком ajax.
— Haniye Shadman

32

Наведені вище приклади трохи заплутані, і це, мабуть, найкращий спосіб:

$.ajaxSetup({
  headers: {
    'Authorization': "Basic " + btoa(USERNAME + ":" + PASSWORD)
  }
});

Я взяв сказане з поєднання відповіді Ріко та Йоссі.

Btoa функція Base64 кодує рядок.


5
Це погана ідея, оскільки ви надішлете інформацію для входу з усіма запитами AJAX, незалежно від URL-адреси. Крім того, у документації $.ajaxSetup()зазначається "Встановити значення за замовчуванням для майбутніх запитів Ajax. Її використання не рекомендується ".
— Zero3

27

Як запропонували інші, ви можете встановити ім'я користувача та пароль безпосередньо під час виклику Ajax:

$.ajax({
  username: username,
  password: password,
  // ... other parameters.
});

АБО використовуйте властивість заголовків, якщо ви бажаєте не зберігати свої облікові дані у простому тексті:

$.ajax({
  headers: {"Authorization": "Basic xxxx"},
  // ... other parameters.
});

Куди б ви не надіслали, сервер повинен бути дуже ввічливим. Для Apache ваш файл .htaccess повинен виглядати приблизно так:

<LimitExcept OPTIONS>
    AuthUserFile /path/to/.htpasswd
    AuthType Basic
    AuthName "Whatever"
    Require valid-user
</LimitExcept>

Header always set Access-Control-Allow-Headers Authorization
Header always set Access-Control-Allow-Credentials true

SetEnvIf Origin "^(.*?)$" origin_is=$0
Header always set Access-Control-Allow-Origin %{origin_is}e env=origin_is

Пояснення:

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

Потім надішліть кілька заголовків, щоб повідомити веб-переглядачу, що йому дозволяється аутентифікуватись, а Access-Control-Allow-Origin надати дозвіл на запит між сайтом.

У деяких випадках * wildcard не працює як значення для Access-Control-Allow-Origin: Вам потрібно повернути точний домен виклику. Використовуйте SetEnvIf, щоб захопити це значення.


5
Дякуємо за інформацію про те, що браузери надсилають запит на попередній політ CORS без автентичних заголовків! Такі деталі можуть викликати години налагодження!
— jbandi

23

Використовуйте функцію jQuery ajaxSetup , яка може встановити значення за замовчуванням для всіх запитів ajax.

$.ajaxSetup({
  headers: {
    'Authorization': "Basic XXXXX"
  }
});

11

JSONP не працює з базовою аутентифікацією, тому зворотний виклик jQuery beforeSend не буде працювати з JSONP / Script.

Мені вдалося подолати це обмеження, додавши до запиту користувача та пароль (наприклад, користувач: pw@domain.tld). Це працює майже з будь-яким браузером, окрім Internet Explorer, де автентифікація через URL-адреси не підтримується (виклик просто не виконується).

Див. Http://support.microsoft.com/kb/834489 .



Ланка розірвана (404).
— Пітер Мортенсен

10

Існує 3 способи досягти цього, як показано нижче

Спосіб 1:

var uName="abc";
var passwrd="pqr";

$.ajax({
    type: '{GET/POST}',
    url: '{urlpath}',
    headers: {
        "Authorization": "Basic " + btoa(uName+":"+passwrd);
    },
    success : function(data) {
      //Success block  
    },
   error: function (xhr,ajaxOptions,throwError){
    //Error block 
  },
});

Спосіб 2:

var uName="abc";
var passwrd="pqr";

$.ajax({
    type: '{GET/POST}',
    url: '{urlpath}',
     beforeSend: function (xhr){ 
        xhr.setRequestHeader('Authorization', "Basic " + btoa(uName+":"+passwrd)); 
    },
    success : function(data) {
      //Success block 
   },
   error: function (xhr,ajaxOptions,throwError){
    //Error block 
  },
});

Спосіб 3:

var uName="abc";
var passwrd="pqr";

$.ajax({
    type: '{GET/POST}',
    url: '{urlpath}',
    username:uName,
    password:passwrd, 
    success : function(data) {
    //Success block  
   },
    error: function (xhr,ajaxOptions,throwError){
    //Error block 
  },
});

8

Відповідно до відповіді SharkAlley, вона працює і з nginx.

Я шукав рішення для отримання даних jQuery з сервера, що знаходиться за nginx та обмеженим Base Auth. Це працює для мене:

server {
    server_name example.com;

    location / {
        if ($request_method = OPTIONS ) {
            add_header Access-Control-Allow-Origin "*";
            add_header Access-Control-Allow-Methods "GET, OPTIONS";
            add_header Access-Control-Allow-Headers "Authorization";

            # Not necessary
            #            add_header Access-Control-Allow-Credentials "true";
            #            add_header Content-Length 0;
            #            add_header Content-Type text/plain;

            return 200;
        }

        auth_basic "Restricted";
        auth_basic_user_file /var/.htpasswd;

        proxy_pass http://127.0.0.1:8100;
    }
}

І JavaScript-код:

var auth = btoa('username:password');
$.ajax({
    type: 'GET',
    url: 'http://example.com',
    headers: {
        "Authorization": "Basic " + auth
    },
    success : function(data) {
    },
});

Стаття, яка мені здається корисною:

  1. Відповіді на цю тему
  2. http://enable-cors.org/server_nginx.html
  3. http://blog.rogeriopvl.com/archives/nginx-and-the-http-options-method/
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.