Сделайте http запрос с ajax для базовой авторизации и cors - PullRequest
0 голосов
/ 01 сентября 2018

Конфигурация для моего httpd-сервера 111.111.111.111 (предполагается).
Конфиг для cors и базовой аутентификации в /etc/httpd/conf/httpd.conf.

<Directory "/var/www/html">
    Options Indexes FollowSymLinks
    AllowOverride AuthConfig
    Require all granted
    Header always set Access-Control-Allow-Origin "*"
    Header always set Access-Control-Allow-Methods "POST, GET, PUT, DELETE, OPTIONS"
    Header always set Access-Control-Allow-Credentials "true"
    Header always set Access-Control-Allow-Headers "Authorization,DNT,User-Agent,Keep-Alive,Content-Type,accept,origin,X-Requested-With"
</Directory>

Создайте еще несколько настроек для базовой авторизации на моем сервере 111.111.111.111.

cd /var/www/html && vim .htaccess
AuthName "login"  
AuthType Basic  
AuthUserFile /var/www/html/passwd  
require user username 

Создать пароль для имени пользователя.

htpasswd -c /var/www/html/passwd username

Перезагрузите httpd с помощью:

systemctl restart httpd

/var/www/html/remote.html на сервере 111.111.111.111.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="Access-Control-Allow-Origin" content="*" />
</head>
<body>
<p>it is a test </p>
</body>
</html>

Протестируйте его с именем пользователя и паролем, когда открывать 111.111.111.111\remote.html?username=xxxx&password=xxxx в браузере.

it is a test

Получить заголовок ответа с помощью curl.

curl -u xxxx:xxxx -I  http://111.111.111.111/remote.html
HTTP/1.1 200 OK
Date: Thu, 06 Sep 2018 00:59:56 GMT
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.16
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Authorization,X-PINGOTHER,DNT,User-Agent,Keep-Alive,Content-Type,accept,origin,X-Requested-With
Last-Modified: Wed, 05 Sep 2018 15:01:05 GMT
ETag: "f5-575210b30e3cb"
Accept-Ranges: bytes
Content-Length: 245
Content-Type: text/html; charset=UTF-8

Добавить параметр OPTIONS в заголовок.

curl -X OPTIONS -i http://111.111.111.111/remote.html

HTTP/1.1 401 Unauthorized
Date: Thu, 06 Sep 2018 06:42:04 GMT
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.16
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Authorization,X-PINGOTHER,DNT,User-Agent,Keep-Alive,Content-Type,accept,origin,X-Requested-With
WWW-Authenticate: Basic realm="please login"
Content-Length: 381
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>401 Unauthorized</title>
</head><body>
<h1>Unauthorized</h1>
<p>This server could not verify that you
are authorized to access the document
requested.  Either you supplied the wrong
credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.</p>
</body></html>

Добавьте OPTIONS и базовую авторизацию в шапке.

curl -X OPTIONS -u xxxx:xxxxx  -i http://111.111.111.111/remote.html

HTTP/1.1 200 OK
Date: Thu, 06 Sep 2018 06:42:54 GMT
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.16
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Authorization,X-PINGOTHER,DNT,User-Agent,Keep-Alive,Content-Type,accept,origin,X-Requested-With
Allow: POST,OPTIONS,GET,HEAD,TRACE
Content-Length: 0
Content-Type: text/html; charset=UTF-8

Хорошо, все в хорошем состоянии.
Давайте попробуем базовую авторизацию ajax.

/var/www/html/test.html на моем локальном apache.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <script src="http://127.0.0.1/jquery-3.3.1.js"></script>
    <script>
    function Ajax( ) {
        var url = 'http://111.111.111.111/remote.html';
        $.ajax(url, {
            type:"get",
            dataType: 'html',
            withCredentials: true,
            username: "xxxx",
            password: "xxxx",
            success:function(response){
                mytext = $("#remote");
                mytext.append(response);
            },
            error: function (e) {
                alert("error");
            }    
        });
    };
    </script>

    <input type="button" value="show content" onclick="Ajax();">
    <p id="remote">the content on remote webpage</p>
</body>
</html>

Чтобы нажать кнопку show content при вводе 127.0.0.1/test.html, я получил ошибку:

GET http://111.111.111.111/remote.html 401 (Unauthorized)

enter image description here

Я дал подробное описание, основанное на настройке httpd (centos7) и ajax и других, связанных с этой проблемой. Загрузите мой код и сохраните его в своем каталоге vps и локальном htdocs, замените ip реальным ip, воспроизведите процесс .
Я прошу вас не делать никаких комментариев, пока вы не воспроизведете процесс.
Вы можете найти то, что случилось, может быть, это то же самое, что и здесь.

Два важных элемента в проблеме.
Настройка 1.httpd в файле /etc/httpd/conf/httpd.conf.
2.ajax код
Какой из них не так?
Как это исправить?

У меня есть ключ к решению проблемы, спасибо @ sideshowbarker.

причина

Проблема превращается в другую:
Как настроить apache так, чтобы он не требовал авторизации для запросов OPTIONS?
Я пытался, как Disable authentication for HTTP OPTIONS method (preflight request) сказать.

Отключить аутентификацию для метода HTTP OPTIONS (предварительный запрос) e

<Directory "/var/www/html">
<LimitExcept OPTIONS>
  Require valid-user
</LimitExcept>
</Directory>

systemctl restart httpd, не удалось.

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

Нет причин использовать <LimitExcept OPTIONS>. Проблема в другом месте:

Если у вас console.log ошибка, вы увидите сообщение:

Не удалось загрузить http://111.111.111.111/remote.html: Значение заголовка «Access-Control-Allow-Origin» в ответе не должно быть подстановочным знаком «*», если режим учетных данных запроса имеет значение «include». Источник 'http://127.0.0.1/', следовательно, не имеет доступа. Режим учетных данных запросов, инициируемых XMLHttpRequest, управляется атрибутом withCredentials.

Это для защиты от атак CSRF. Например. SiteA может получить доступ к привилегированным ресурсам без авторизации на SiteB через запросы ajax, просто потому что учетные данные для SiteB были предоставлены пользователем ранее при SiteC.

Таким образом, решение состоит в том, чтобы просто изменить Access-Control-Allow-Origin с "*" на "http://127.0.0.1"

Примечание. Я использовал последнюю версию jquery и, как описано в документе, добавил withCredentials следующим образом:

xhrFields: {
      withCredentials: true
}


Теперь на случай, если вам интересно, как работает для curl -X OPTIONS -i http://111.111.111.111/remote.html при сохранении активной аутентификации для других методов: добавьте это, чтобы добавить это к .htaccess или httpd.conf. Но, опять же, я думаю, что никакой дополнительной выгоды от этого нет.

<LimitExcept OPTIONS>
   AuthName "login"
   AuthType Basic
   AuthBasicProvider file
   AuthUserFile /var/www/cors-auth.passwd
   require user username
 </LimitExcept>

EDIT:

LimitExcept OPTIONS действительно требуется, если вам нужно предварительно ввести имя пользователя / пароль (как в вашем случае), вместо того, чтобы ожидать, что браузер выведет диалоговое окно. Но чтобы он работал во всех браузерах (chrome / ff / edge), Я должен был заменить это:

        withCredentials: true,
        username: "xxxx",
        password: "xxxx",

с этим:

      beforeSend: function (xhr){ 
           xhr.setRequestHeader('Authorization', "Basic " + btoa("xxxx:xxxx")); 
       },
0 голосов
/ 11 сентября 2018

попробуйте поставить localhost вместо 'http://111.111.111.111/remote.html'

'http://localhost/remote.html. Это должно работать. Это может быть проблема с вашим публичным IP-адресом, когда порт 80 не открыт.

...