如何保护跨域请求;允许第三个网站发布数据

Posted

技术标签:

【中文标题】如何保护跨域请求;允许第三个网站发布数据【英文标题】:How to secure Cross-Domain request; allowing third website to POST data 【发布时间】:2014-06-27 20:46:53 【问题描述】:

我对如何防止虚假跨域请求做了一些研究,发现了很多有用的信息。但是,它们似乎都没有直接解决我的顾虑,而且由于我的应用程序必须处理这种特定情况,我想完全理解它。

我有一个简单的 php 邮件网站:mailsite.com

本站点将允许其他预定义地址,例如user.com,向其发送POST数据,并处理包含tomesaage的信息;然后从 mailsite.com 向他们发送一封电子邮件至to,并附上消息message

目前,我正在使用$_SERVER[ "HTTP_ORIGIN" ]$_SERVER[ "HTTP_REFERER" ] 来检查请求的来源;如果它来自预定义的域,则对其进行处理。但是,我读过一些文章说:

    HTTP_ORIGIN 甚至没有在 PHP 文档中编入索引,因为它几乎是针对每个浏览器的,因此拒绝发送这些信息的浏览器将无法工作。 HTTP_REFERER 很容易伪造。 token 可以很好地防止 CSRF。

但是,我允许的请求来自第三个预定义网站,令牌在这种情况下如何工作?

我的问题是:如果我允许特定域向我的网站发布数据,我如何确保(或最安全的方式)这些请求来自我预期的网站? HTTP_ORIGIN 使用起来还不够安全吗?我敢于考虑允许第三个网站向我的网站发布数据,因为我已经看到 Facebook 允许人们访问他们的数据库。必须有一些可能的解决方案来检查请求的来源。

【问题讨论】:

我确定您的意思是$_SERVER[ "HTTP_REFFERAL" ] 对吧?你打错字了。 是的。我很抱歉错字。我是用手机打出来的。非常感谢您指出这一点。 是否需要支持不支持CORS的浏览器?否则不清楚你的担忧是什么...... @Fred-ii 我确定你的意思是$_SERVER['HTTP_REFERER'] 对吧? ;) 是的@GeorgeCummins 我也站得住脚。我从 OP 的original post 中获取它。忘记了下划线。 【参考方案1】:

听起来您有多种可能的解决方案:

使用令牌权限系统。为 user.com 提供一个私有令牌,以将其作为隐藏值添加到输入表单中。提交此表单后,浏览器将向您的服务器提供令牌,用户不必知道令牌。您根据自己的数据库检查令牌。如果找到令牌,则允许发送邮件。

使用 CORS(跨域资源共享)。当从 user.com 向您的服务器发送 Ajax 请求时,应该有多个 Access-Control 标头。您检查这些是否存在以及它们的值使用$_SERVER['HTTP_ACCESS_CONTROL_header'],其中headerAccess-Control 标头名称之一。如果这些值符合您的预期,请使用多个 header('Access-Control-header: value'); 调用响应,以便浏览器知道您接受了预检请求,否则不要添加任何额外的标头。浏览器将在预检后发送另一个请求,这就是您实际发送邮件的时间。

如果这是从 user.com 的服务器而不是 user.com 的访问者发送的,则服务器的 IP 地址很可能不会改变(尽管它可能使用也可能不使用定义的 IP 范围,所以请注意这一点。),因此您可以验证 $_SERVER['REMOTE_ADDR'] 是否与数据库中的值匹配。为此,您可以在数据库中保留一张批准的 IP 地址表。如果您在表中找到 IP 地址,则允许发送邮件。

希望这会有所帮助。

【讨论】:

关于第三点,我认为这样做不是一个好习惯,如果 user.com 在共享主机上怎么办? 然后它变得有点棘手。您可以保留一张已批准域名的表格,然后是该域名的 IP 地址。使用在 cronjob 上执行的脚本定期查找每个域名并将其 IP 映射到您的数据库中,删除不再出现在查找中的该域的旧条目,并添加查找找到的任何新 IP。当请求进来时,验证这些 IP 中的任何一个。您还可以添加检查该 IP 的反向 DNS,并查看其 DNS 是否在您批准的域名中。 共享主机=多域单ip。 嗨 Jailout2000。非常感谢您的回答。我可以问两个简单的问题吗? 1) 用户A访问site.com; REMOTE_ADDR 是返回用户 A 的 IP 还是 site.com 的 IP? 2)现在对我来说似乎只有 CORS 是可能的,你有一个非常快速和基本的服务器端示例吗?我查了一下,好像只是比 HTTP_ORIGIN 多一点,而 HTTP_ORIGIN 并不是很可靠。 HTTP_ACCESS_CONTROL_header 是可以使用 javascript 编码的东西,这意味着它很容易受到攻击,不是吗? @user3622260 第一个问题的答案是:它会返回site.com的IP。

以上是关于如何保护跨域请求;允许第三个网站发布数据的主要内容,如果未能解决你的问题,请参考以下文章

跨域请求(CORS)要点

允许跨域 ajax 请求中的标头

浏览器是不是允许“发送”跨域请求?

前后端分离,解决跨域问题及django的csrf跨站请求保护

如何实现跨域请求的csrf保护

允许跨域ajax请求