使用ajax发出http请求以获取基本授权和更正

时间:2018-09-01 07:41:27

标签: javascript apache authentication cors jqxhr

我的httpd服务器111.111.111.111的配置(假定)。
/etc/httpd/conf/httpd.conf中配置cors和基本身份验证。

<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

使用:p重新启动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的基本授权。

我本地apache上的/var/www/html/test.html

<!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.文件/etc/httpd/conf/httpd.conf中的httpd设置。
2.ajax代码
哪一个错了?
如何解决?

由于@sideshowbarker,我有一些解决问题的线索。

reason

问题又变成了另一个问题:
如何将apache配置为不要求OPTIONS请求授权?
我已经按照Disable authentication for HTTP OPTIONS method (preflight request)的方式尝试过。

Disable authentication for HTTP OPTIONS method (preflight request)e

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

systemctl restart httpd,失败。

2 个答案:

答案 0 :(得分:1)

尝试将localhost而不是'http://111.111.111.111/remote.html'

'http://localhost/remote.html。它应该可以工作。这可能是您的公共ip地址问题,其中80端口未打开。

答案 1 :(得分:1)

没有理由使用<LimitExcept OPTIONS>。问题出在其他地方:

如果您console.log错误,您将看到一条消息:

  

无法加载http://111.111.111.111/remote.html:当请求的凭据模式为“ include”时,响应中“ Access-Control-Allow-Origin”标头的值不能为通配符“ *”。因此,不允许访问来源“ http://127.0.0.1/”。 XMLHttpRequest发起的请求的凭据模式由withCredentials属性控制。

这是为了保护CSRF攻击。例如。 SiteA可以通过ajax请求在SiteB上未经授权访问特权资源,这是因为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或{ {1}}。 但是我仍然认为没有任何额外的收获。

httpd.conf

编辑:

如果您需要预填用户名/密码(如您的情况),则实际上需要

<LimitExcept OPTIONS> AuthName "login" AuthType Basic AuthBasicProvider file AuthUserFile /var/www/cors-auth.passwd require user username </LimitExcept> ,而不是期望浏览器提示对话框。但是要使其在所有浏览器(chrome / ff / edge)上都能正常工作, 我不得不替换它:

LimitExcept OPTIONS

与此:

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