Використовуйте базову автентифікацію за допомогою 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.