通过AJAX获取在服务器上调用PHP文件的域

时间:2011-08-04 18:35:28

标签: php ajax api referer

我正在构建一个API,并对如何跟踪/了解哪些域名使用该号码提出疑问。

API调用是用PHP构建的,不需要任何身份验证。用户很可能在其服务器上的AJAX调用中使用API​​。

例如,我提供API PHP文件的域称为dev.yourmapper.com。域名www.metromapper.org上的某人构建了一个创建Go​​ogle地图的页面,并使用Ajax调用我的文件将我的数据叠加到他们的地图上。

以下是实施例:http://www.metromapper.org/example/apitest.htm

(单击中心地图标记以查看yourmapper.com脚本可用的所有PHP服务器变量的弹出窗口。)

请注意,如果单击链接,HTTP_REFERER可能会变为'stackoverflow.com'(如果您剪切并粘贴链接,则为空)。我认为引用者将是metromapper.org,因为该域在加载后调用了yourmapper.com脚本,但显然不是。

结论:我可以使用哪种方法来确定哪个域使用Javascript调用mymapper.com脚本?如果需要,我可以使用PHP以外的其他语言。感谢。

2 个答案:

答案 0 :(得分:3)

“我认为referer将是metromapper.org,因为该域在加载后会调用yourmapper.com脚本”

实际上这是不正确的。首先,你不应该依赖HTTP_REFERER,因为它是大多数(不是所有)浏览器传递的自愿参数,并且很容易被欺骗。我可以使用CURL发送您的网站请求,如果我愿意,看起来像推荐人是whitehouse.gov。那里没有安全措施。

话虽如此。浏览器将该参数设置为将用户引用到当前加载页面的页面。不是脚本。因此,您看到结果的原因是因为用户通过stackoverflow.com上的链接被引用到metromapper.org

最后,让我们来看看多汁的部分。您正在使用JS在浏览器中编写代码。那没关系,这绝对没有问题。但你必须记住JS是开源的。因此,人们可以(并且将会)将您的代码与您的API一起使用,因为他们可以。话虽如此。你最好的选择可能是在你的JS api中传递网站的url和请求。这是“跟踪”网站使用您的脚本的最佳方式。您可以检查服务器端以确保传递了URL。这会阻止人们修改您的API以删除将其URL发送到您的服务器的位。但是,它不会阻止他们修改它以使用其他人的网址或随机未注册的网址作为参数。

当然,您可以构建一个在其服务器上运行的PHP API。 JS API连接到PHP API,PHP API是zend-guard编码的(或其他一些源代码保护代码系统)但是仍然会有人解码文件以回到你的源代码并弄乱你。当然,人们能够做到这一点的人数要少得多,而普通用户更愿意使用你的API。然后,您还遇到了无法在无法运行编码的PHP文件的服务器上运行API的问题。

最后,您必须确定所需的安全性和身份验证级别,但由于您的API在客户端浏览器中使用JavaScript运行,因此除了混淆之外几乎没有。

我想说你最好的选择就是让你的JS代码抓住当前页面的URL并通过API请求发送它。从那里,您的服务器可以处理URL以获取根域和您要存储的任何其他信息。

如果您想阻止人们“欺骗”其他用户网站网址的请求,您可以实现在某个地方安装在用户服务器上的PHP API。例如http://www.domain.com/my-app-name.php

所有JS API调用都应该通过该脚本。当用户下载您的API时,他们应该输入他们的网站URL和其他一些信息。您的系统会生成一个“密钥”并将其注入脚本,然后再打包以供下载。该密钥对其域有效,并用于使用说blowfish或其他双向加密算法对进出API的所有传输进行编码。这样,当您的API从其PHP API文件收到请求时,您将获得请求所依据的页面的URL,并使用仅由您和该站点的管理员拥有的密钥进行编码。所以请求就是这样的:metromapper.org/api?site=[url_encoded_pa​​ge_address]&req=[encrypted_request]

您的服务器使用页面网址来确定应使用哪个密钥来解密数据。然后它解密数据。如果数据已损坏或未解密为您所期望的数据,那么这是一个无效的请求,您应该退出任何内容。

我建议使用PHP文件进行加密而不是将加密写入JS的原因是因为您不希望给客户端(每个站点访问者)带来加密/解密负担,并且PHP将要处理它比JS快得多,因为有些库可以帮你处理这些任务。

无论如何,您应该能够跟踪和验证针对您的API的不同网站的请求。

答案 1 :(得分:1)

您可以根据域名生成哈希值,并让API的用户在每个请求中发送域名和哈希值。现在,既然您的API使用了PHP,那么您已经设置了“访问控制 - 允许 - 来源”#39;标题中的某个地方。如果你在PHP中这样做,你可以玩一下。下面的脚本是一个简单的示例,说明在调用者方面不需要php的实现(使用您的域的API)。

来电方(不需要php):

<script type="text/javascript">
  function callA() {
    var xhttp = new XMLHttpRequest();
    xhttp.open("GET", "//ajaxdomain.com/call.php?"+
                      "dom=www.callerdomain.com&"+
                      "key=41f8201df6cf1322cc192025cc6c5013",
               true);
    xhttp.onreadystatechange = function() {
      if(xhttp.readyState == 4 && xhttp.status == 200) {
        handleResponse(xhttp.responseText);
      }
    }
    xhttp.send();
  }
</script>

Ajax服务器端(PHP):

<?php
  if($_GET['key']==md5($_GET['dom']."Salt")) {
    header("Access-Control-Allow-Origin: http://".$_GET['dom']);
  }
?>

这样,如果来自恶意域的呼叫,也会放置标头,但是由于交叉原点异常,休息将会反弹,因此不会给出结果。

为了代码空间,我在此示例中使用了md5哈希,但如果需要,可以使用更复杂的哈希值。请注意,您应该(一如既往)将使用过的盐保密。

我在以下(子)域中在线提供了一个工作示例。页面完全相同。

cors1.serioushare.com - 仅适用于CORS 1&#39;按钮。
cors2.serioushare.com - 仅适用于CORS 2&#39;按钮。