JQuery Ajax вызывает с базовой аутентификацией HTTP - PullRequest
28 голосов
/ 14 марта 2012

У меня есть сервер на основе REST, с которым я пытаюсь установить связь с помощью JQuery. И XML, и JSON доступны как форматы ответов, поэтому я использую JSON.

Все соединения являются SSL, поэтому для авторизации был выбран метод базовой аутентификации HTTP, и у нас не было проблем с другими интерфейсами (необработанный Javascript, Silverlight и т. Д.)

Теперь я пытаюсь соединить что-то с JQuery и у меня возникают бесконечные проблемы с использованием базовой аутентификации HTTP.

Я изучил многочисленные предыдущие вопросы, большинство из которых либо имеют решения, которые, кажется, не работают, либо винят всю проблему в доступе из разных источников, которую я уже преодолел в базовом тестировании Javascript. В ответах всегда указывается Access-Control-Allow-Origin, установленный на указанный заголовок Origin в запросе, и это можно увидеть в ответах моих тестов.

В базовом javascript весь этот вызов выполняется очень просто:

req.open('GET', 'https://researchdev-vm:8111/card', true, 'test', 'testpassword');

Попытка JQuery сделать это довольно стандартна:

        $.ajax({
        username: 'test',
        password: 'testpassword',
        url: 'https://researchdev-vm:8111/card',
        type: 'GET',
        dataType: 'json',
        crossDomain: true,
        /*data: { username: 'test', password: 'testpassword' },*/
        beforeSend: function(xhr){
            xhr.setRequestHeader("Authorization",
                //"Basic " + encodeBase64(username + ":" + password));
                "Basic AAAAAAAAAAAAAAAAAAA=");
        },
        sucess: function(result) {
            out('done');
        }
    });

Единственный метод, который на самом деле работает для обеспечения аутентификации, - это прямая вставка закодированных в Base64 данных в функцию beforeSend(). Если это не включено, никакого прогресса не будет достигнуто. Свойства имени пользователя и пароля полностью игнорируются.

С предоставленным поведением beforeSend() вызов GET получает положительный ответ с включенными данными. Однако, поскольку это межсайтовый вызов, вызов OPTIONS выполняется перед вызовом GET и всегда завершается ошибкой, поскольку он не использует beforeSend() и поэтому получает ответ 401 из-за неудачной аутентификации.

Есть ли лучший способ выполнить то, что должно быть очень тривиальным вызовом? Должен ли тот факт, что запрос OPTIONS не использует обработку функции beforeSend(), рассматриваться как ошибка? Возможно, есть способ полностью отключить проверку OPTIONS? Невозможно сделать этот вызов не межсайтовым, поскольку Javascript рассматривает даже другой номер порта на той же машине, что и «межсайтовый».

Ответы [ 3 ]

3 голосов
/ 27 ноября 2012

Этот вопрос, вероятно, уже давно истек, но я работал с той же вещью в Jquery и столкнулся с той же проблемой.

Кажется, что атрибуты имени пользователя и пароля не выполняют кодирование base64 имени пользователя / пароля, как вы обычно делаете для базовой HTTP-аутентификации.

Посмотрите на следующие запросы (сокращенно для краткости), во-первых, используя параметры "username" и "password" в методе JQuery AJAX:

Request URL:http://testuser%40omnisoft.com:testuser@localhost:60023/Account
Request Method:GET
Accept:application/json, text/javascript, */*; q=0.01
Host:localhost:60023

А теперь с методом beforeSend:

Request URL:http://localhost:60023/Account
Request Method:GET
Accept:application/json, text/javascript, */*; q=0.01
Authorization:Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Host:localhost:60023

Обратите внимание, что первый метод не включает в запрос заголовок «Авторизация», а вместо этого ставит префикс целевого URL. Я не эксперт по базовой аутентификации HTTP, но это указывает на то, что первая не является правильной реализацией и поэтому дает сбой (или, по крайней мере, это происходит с моей собственной реализацией сервера).

Что касается вашего запроса OPTIONS с использованием JSONP - вы можете попытаться использовать ?callback=? в своем URL вместо опции crossdomain, просто чтобы быть явным.

1 голос
/ 09 октября 2013

Для всех, кто столкнулся с этой проблемой, я решил проблему с перехватом запросов OPTIONS с помощью Apache и пересылкой только GET и POST на серверную часть.

Это решение не зависит от сервера приложений и поэтому работает для PHP и Java.а также:

<VirtualHost *:80>

    # ServerName and other configuration...


    # CORS
    Header set Access-Control-Allow-Origin "*"
    Header set Access-Control-Allow-Methods "OPTIONS, GET, PUT, POST" 
    Header set Access-Control-Allow-Headers "Authorization"

    # Intercept OPTIONS calls
    RewriteEngine On
    RewriteCond %{REQUEST_METHOD} ^(OPTIONS)$
    RewriteRule .* - [L]

    # Backend, adapt this line to fit your needs
    RewriteRule /(.*) ajp://localhost:8010/$1 [L,P]

</VirtualHost>

С уважением, Маурицио

1 голос
/ 27 июня 2012

Вот что-то, что действует как сквозная аутентификация для вызовов AJAX.Это основывается на NTLM для аутентификации на странице, с которой будет выполняться JavaScript.Может быть, это поможет вам:

Код PHP:

<?php 
$headers = apache_request_headers();
if (isset($headers['Authorization'])) 
   echo "<script>var auth = " . $headers['Authorization'] . "</script>";
unset($headers);
?>

Используя jQuery, вы можете использовать его следующим образом:

$.ajax({
        type: 'POST',
        url: './somePage.php',
        data: {"test":true},
        dataType: 'json',
        success: function(data) {
            console.log(data.username);
        },
        beforeSend : function(req) {
            req.setRequestHeader('Authorization', auth); // <<<<----- USED HERE
        },
});

Для стандартного XMLHttpRequest:

var xml = new XMLHttpRequest();
xml.open('GET', './somePage.php', true);
xml.setRequestHeader('Authorization', auth); // <<<<----- USED HERE
xml.send();
...