我的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)
我已经基于httpd设置(centos7)和Ajax等与该问题相关的其他内容进行了详细说明,请下载我的代码并将其保存在您的vps和本地htdocs目录中,用真正的ip替换ip,重现该过程。
我求求您在重现该过程之前不要发表任何评论。
您可能会发现发生了什么事,也许与我的情况相同。
此问题中的两个重要要素。
1.文件/etc/httpd/conf/httpd.conf
中的httpd设置。
2.ajax代码
哪一个错了?
如何解决?
由于@sideshowbarker,我有一些解决问题的线索。
问题又变成了另一个问题:
如何将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
,失败。
答案 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",