Подтвердить что ты не робот

JQuery Ajax вызывает базовую аутентификацию HTTP

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

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

Теперь я пытаюсь собрать что-то вместе с JQuery и иметь бесконечные проблемы с использованием HTTP Basic Authentication.

Я просмотрел многочисленные предыдущие вопросы, большинство из которых либо имеют решения, которые, по-видимому, не работают, и не обвиняют всю проблему в доступе к кросс-контенту, что я уже преодолел в основном тестировании 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, похоже, рассматривает даже другой номер порта на той же машине, что и "кросс-сайт".

4b9b3361

Ответ 1

Этот вопрос, вероятно, прошел уже по истечении срока его действия, но я работал с одним и тем же с JQuery и столкнулся с одной и той же проблемой.

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

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

Request URL:http://testuser%40omnisoft.com:[email protected]: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, просто чтобы быть явным.

Ответ 2

Здесь что-то, что действует как сквозная аутентификация для вызовов 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();

Ответ 3

Для всех, кто приходит через эту проблему, я решил проблему перехвата запросов 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>

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