【问题标题】:Prevent direct access to a PHP page防止直接访问 PHP 页面
【发布时间】:2010-09-16 04:12:51
【问题描述】:

如何防止我的用户直接访问仅用于 ajax 调用的页面?

在 ajax 调用期间传递密钥似乎是一种解决方案,而没有密钥的访问将不会被处理。但是,制造钥匙也很容易,不是吗?查看源码的诅咒...

p/s:使用 Apache 作为网络服务器。

编辑:要回答为什么,我的 index.php 中有 jQuery ui-tabs,在这些选项卡中是带有脚本的表单,如果直接访问它们将不起作用。为什么用户会想要这样做,我不知道,我只是想通过防止在没有验证脚本的情况下直接访问表单,我会更加用户友好。

【问题讨论】:

  • 在这种情况下不要担心用户友好性。事实上,我会说你最好早点失败,而不是试图让它变得愉快。例如,假设您将其重定向到 index.php 以进行非 AJAX 访问。结果:肯定有人会为 AJAX 脚本添加书签,因为它会将它们带到您的主页。

标签: php ajax apache


【解决方案1】:

在调用脚本的javascript文件中:

var url = "http://website.com/ajax.php?say=hello+world";
xmlHttp.open("GET", url, true);
xmlHttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

然后在php文件ajax.php中:

if($_SERVER['HTTP_X_REQUESTED_WITH'] != "XMLHttpRequest") {
    header("Location: http://website.com");
    die();
}

Geeks 仍然可以通过伪造标头来调用 ajax.php 脚本,但我的脚本的其余部分需要会话,因此在未检测到有效会话时执行结束。我需要它来工作,以便将具有过期混合身份验证会话的人重定向到主站点,以便再次登录,因为他们最终被重定向到 ajax 脚本。

【讨论】:

    【解决方案2】:

    谢谢,虽然我用过

    define('IS_AJAX', isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
    
    if(IS_AJAX) {
        //Request identified as ajax request
    }
    

    干杯!

    【讨论】:

      【解决方案3】:

      通过 index.php 传递您的直接请求,通过 ajax.php 传递您的 ajax 请求,然后不要让用户直接浏览到任何其他源文件 - 确保 index.php 和 ajax.php 具有适当的逻辑来包含他们需要的代码。

      【讨论】:

        【解决方案4】:

        COOKIES 不安全...试试 $_SESSION。这几乎是您实际上可以依赖的无法欺骗的跨页面的少数几件事之一。因为,当然,它基本上永远不会脱离您的控制。

        【讨论】:

          【解决方案5】:

          这对于保护某些东西绝对没有用.. 但我认为如果你想说一个 php 页面如果页面不是由 ajax 请求而生成整个页面但只生成部分您需要在使用 ajax 时返回。这将允许您使您的网站对 ajax 不友好,所以如果说他们点击一个链接并且它应该加载一盒 cmets 但他们没有 ajax 它仍然会将它们发送到然后生成一个显示 cmets 的整个页面。

          【讨论】:

            【解决方案6】:

            对此不确定,但可能会检查引荐来源标头?我认为如果有人手动输入您的网址,它不会有引荐来源标头,而 AJAX 调用有(至少在我刚刚在我的系统上进行的快速测试中)。

            不过,这是一种不好的检查方式。由于很多原因,推荐人可能为空白。您是否试图阻止人们将您的网络服务用作公共服务或其他什么?

            阅读您的编辑 cmets 后,如果表单将通过 ajax 调用加载,您可以检查 window.location 以查看该 url 是否是您的 ajax 表单的 url。如果是,请通过 document.location 转到正确的页面

            【讨论】:

            • 非常容易伪造referrer header。
            • @Alex Right,这将是“由于多种原因可能为空白”声明中包含的原因之一。此页面上的任何回答都可能被伪造,因为它们都是客户端输入法——客户端发送到服务器的数据。将此页面上的每个答案都标记为否定。
            【解决方案7】:

            正如其他人所说,可以通过创建正确的标头来模拟 Ajax 请求。 如果您想进行基本检查以查看请求是否为 Ajax 请求,您可以使用:

             if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
                 //Request identified as ajax request
             }
            

            但是,您永远不应将您的安全性建立在此检查之上。如果您需要,它将消除对页面的直接访问。

            【讨论】:

            • 我得到未定义的索引:HTTP_X_REQUESTED_WITH。你的意思是我必须自己分配那个值吗?
            • 您使用什么框架来处理 Ajax 请求? (我希望你没有使用自制的解决方案......)
            • 而且,该参数也只能在 Ajax 请求中使用。如果您不想要未定义的索引错误,您可能需要添加 isset() 检查
            • Syaz,这不是基本的安全措施。正如 Eran 正确所说的那样 - “你永远不应该将你的安全性建立在这个检查上” 它很容易伪造(我相信 wget 或许多 firefox 插件可以非常简单地做到这一点)你还没有说你为什么想要这个- 有什么可以保护的?
            • 我已经编辑了我的第一篇文章来说明我想要实现的目标——用户友好。就如此容易。 ;)
            【解决方案8】:

            如果浏览器会通过普通请求或 ajax 调用您的页面,那么有人可以手动调用它。就服务器-客户端通信而言,普通请求和 ajax 请求之间确实没有明确的区别。

            常见的情况是向服务器传递一个标头,上面写着“这个请求是由 ajax 完成的”。如果您使用 Prototype,它会自动将 http 标头“X-Requested-With”设置为“XMLHttpRequest”,以及其他一些标头,包括原型版本。 (在“requestHeaders”中查看更多信息:http://www.prototypejs.org/api/ajax/options

            添加:如果您使用另一个 AJAX 库,您可以添加自己的标题。这对于了解服务器端的请求类型以及避免在浏览器中请求 ajax 页面的简单情况很有用。它不能保护您的请求不受所有人的影响,因为您不能。

            【讨论】:

              【解决方案9】:

              听起来您可能以错误的方式处理事情。 AJAX 调用就像一个标准的页面请求,只是按照惯例,响应不打算显示给用户。

              但是,它仍然是客户端请求,因此您必须为客户端能够看到响应感到高兴。以这种方式使用“密钥”混淆访问只会使事情复杂化。

              实际上,我会说视图源的“诅咒”是通过默默无闻对抗安全的小武器。

              那么你想要这样做的原因是什么?

              【讨论】:

              • 我喜欢“通过默默无闻对抗安全的小武器”。部分-介意我引用它一段时间吗? :)
              【解决方案10】:

              无法保证他们通过 AJAX 访问它。直接访问和 AJAX 访问都来自客户端,因此很容易被伪造。

              你为什么要这样做?

              如果是因为 PHP 代码不是很安全,请让 PHP 代码更安全。 (例如,如果您的 AJAX 将用户 ID 传递给 PHP 文件,请在 PHP 文件中编写代码以确保该用户 ID 是正确的。)

              【讨论】:

              • 没什么可说的了。永远不要,永远相信客户发给你的东西。由于 AJAX 方法旨在向浏览器返回内容,因此请确保在后端只能返回授权数据。
              • 我唯一的遗憾是我只有一票可以给这个答案。
              • 我唯一的遗憾是我得了骨炎。
              • 既然他只想要用户友好,那么检查 XMLHttpRequest 似乎是一个很好的解决方案,只要与安全无关。
              猜你喜欢
              • 2010-11-05
              • 2012-05-22
              • 1970-01-01
              • 1970-01-01
              • 2012-09-16
              • 1970-01-01
              • 2011-02-04
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多