我目前正在为所有域(scripts.domain.com)开发一个中央AJAX脚本库。
我有以下PHP代码,理论上可以很好地防止错误的CORS请求。
$valid_cors = array("domain1","domain2","domain3");
if(in_array($_SERVER['HTTP_ORIGIN'],"https://".$valid_cors)) {
header('Access-Control-Allow-Origin: https://{$valid_cors}', false);
header("Access-Control-Allow-Methods: GET, POST, PUT");
header("Access-Control-Allow-Headers: Content-Type");
}
我打赌你可以在你阅读之前猜到我收到的信息。对于那些无法做到的人来说,这就是:
XMLHttpRequest无法加载 https://scripts.domain.com/scripts/ajax_caller.json? No' Access-Control-Allow-Origin'标题出现在请求的上 资源。起源' https://domain1'因此是不允许的 访问。
在这里阅读了一些问题之后,我的理解是大多数浏览器甚至都不发送HTTP_ORIGIN标题,所以基本上整个ACAO系统都是毫无意义的,因为你必须放弃Allow - 打印为星号,允许多个域调用它。您也不能放置多个A-O标头,因为如果有多个A-O标头,浏览器会完全阻止该请求。
我们现在都知道 - 不要相信任何浏览器发送给你的东西,因为它很容易被伪造,所以为什么这甚至被认为是实现的呢?
使用星号系统对我没有任何好处,因为我们检查了CSRF&在调用任何操作文件之前执行会话,但是对于大多数用户来说,这可能会带来更多的弊大于利,从而使他们陷入虚假的安全感。
拜托,有人可以告诉我,我在这里得到了错误的结论并且我使用它错了吗?似乎没有多少人可以给出答案栏星号,这让我更加确信这是唯一的方法。
答案 0 :(得分:5)
在这里阅读了一些问题之后,据我所知,大多数浏览器甚至都不发送HTTP_ORIGIN标题
嗯,那不是真的。任何支持CORS的东西都支持发送Origin
请求标题。
因为你必须把Allow-Origin作为星号,以允许多个域来调用它
不,那也不是真的。您的服务器可以根据不同的来源做出不同的响应。
例如,如果请求包含Origin: a.example.com
,则您可以使用Access-Control-Allow-Origin: a.example.com
进行回复。
如果Origin: b.example.com
发出请求,请回复Access-Control-Allow-Origin: b.example.com
。
我们现在都知道 - 不要相信任何浏览器发送给你的东西,因为它很容易被伪造,所以为什么这甚至被认为是实现的呢?
CORS不用于保护服务器资源。这是为了隔离客户端访问。
如您所知,网页可以包含来自多个来源的数据。我们一直使用图像,脚本等来执行此操作。但是,这只允许我们查看来自多个来源的内容。它不允许来自多个来源的脚本看到彼此的数据。
假设情况并非如此......并且您可以制作跨域AJAX请求。假设我有一个关于投资建议的热门博客。我知道读我博客的人最近也可能登录了他们的经纪网站。我可以在我的博客网站上安装一个脚本,该脚本会向经纪网站发出AJAX请求以进行交易。原因是,而不是用户发出请求,现在我正在提出请求......但是使用他们的cookie。我甚至不知道他们会冒充他们!可怕的东西。
在一个更常见的示例中,许多家庭路由器都有具有默认凭据的管理面板。很多这些路由器也没有使用正确的HTTP动词...所以GET请求可以用来做开放端口之类的事情。这些路由器仍然注定失败,因为我可以使用简单的图像标记发出GET请求。像这样:
<img src="http://192.168.1.1/firewall/?action=openPort&port=22" />
(当然“图像”无法加载,但浏览器会发出请求,路由器也会遵守它。)
如果路由器使用了PUT
或POST
等正确的动词,则无法使用简单的图像标记进行此更改。但是如果没有CORS,页面可以使用PUT
或POST
发出AJAX请求,在您不知情的情况下控制您的家庭路由器!基本上,使用您的计算机作为运行特权脚本的地方。
以这种方式防止对资源的跨源访问有助于保护您的特权访问安全。
答案 1 :(得分:0)
我有以下PHP代码[...]
$valid_cors = array("domain1","domain2","domain3"); if(in_array($_SERVER['HTTP_ORIGIN'],"https://".$valid_cors)) { header('Access-Control-Allow-Origin: https://{$valid_cors}', false); header("Access-Control-Allow-Methods: GET, POST, PUT"); header("Access-Control-Allow-Headers: Content-Type"); }
[...]
请,有人可以告诉我,我在这里遇到了错误的情况,而我使用错了吗?
Notice: Undefined index: HTTP_ORIGIN
; Notice: Array to string conversion
+ Warning: in_array() expects parameter 2 to be array, string given
(即"https://Array"
)并且从不输入if
; if
,字符串'Access-Control-Allow-Origin: https://{$valid_cors}'
也将被按字面理解($valid_cors
未展开)因为有单引号(而不是"Access-Control-Allow-Origin: https://{$valid_cors}"
有双引号); Access-Control-Allow-Origin
不接受多个值。无论如何,我想你的意思是这样的:
$valid_cors = array('domain1', 'domain2', 'domain3');
if (isset($_SERVER['HTTP_ORIGIN']) && in_array($_SERVER['HTTP_ORIGIN'], array_map(function ($domain) { return 'https://'.$domain; }, $valid_cors), true)) {
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
header('Access-Control-Allow-Methods: GET, POST, PUT');
header('Access-Control-Allow-Headers: Content-Type');
}
(但是我不确定这将是“针对不良CORS请求的良好保护” ...)