【问题标题】:Is there any way to prevent AJAX pages from being viewed alone in a browser?有什么方法可以防止 AJAX 页面在浏览器中被单独查看?
【发布时间】:2011-04-04 13:25:30
【问题描述】:

例如,当我想用​​ AJAX 更新我的页面的一部分时,我通常会适当地调用 getPost.php,它会返回要插入到我的页面中的标记。有什么方法可以阻止用户直接访问此页面(例如:example.com/getPost.php 使用适当的 GET 或 POST 参数)并仅获取页面的一部分,因为这应该与 AJAX 一起使用作为整体的一部分,不是一个人吗?

我不认为可以在文件上设置权限,因为它是请求页面的客户端,但是有没有办法通过传递一个可以用作各种校验位的额外参数来做到这一点。

【问题讨论】:

  • 没有特别的原因。不应该是超级安全的东西,但足以让用户不会偶然发现网页的一部分而不是整个网页。或者至少有人不会向将信息发送到数据库的 php 页面发送请求。

标签: php ajax security


【解决方案1】:

您可以查看请求标头并强制必须为 AJAX 请求设置标头(人们通常使用 X-Requested-With 和类似 XMLHttpRequest 的值)。请注意,除非您在发出 AJAX 请求时自行设置(或使用自动执行此操作的 Javascript 库),否则不会设置此标头。但是,如果有人愿意,无法保证不会自行添加该标头。

X-Requested-With 标头值可以在$_SERVER['HTTP_X_REQUESTED_WITH'] 中找到。

【讨论】:

  • 感谢您的快速回答,我不知道这个!
【解决方案2】:

您可以检查 $_SERVER['HTTP_X_REQUESTED_WITH'] 标头。如果它是 Ajax 请求,它应该等于值“XMLHttpRequest”。

编辑 - 正如 Daniel Vandersluis 所说,没有办法完全执行此操作。您可以欺骗用户代理、引荐来源网址 - 请求中包含的任何内容。

【讨论】:

    【解决方案3】:

    无论您向服务器请求什么,它都会将信息存储在$_SERVER 变量中

    要检查这个变量存储什么信息试试这个

    print_r($_SERVER);
    
    //you will see the difference in http and ajax request 
    

    使用这个变量来检查如下

    if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
        strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
       //ajajx request
    }
    else {
       //not an ajajx request
    }
    

    【讨论】:

      【解决方案4】:

      由于无法 100% 确定提问者是谁,因此您可以限制问题本身。

      这当然取决于页面的实现。

      例如,假设您在 url 上运行 curl 命令,您可以将传入变量限制为仅某个域。

      <?php
      if (substr($_GET["url"], 0, 19) !== "http://example.com/")
      {
          die();
      }
      // otherwise carry on
      ?>
      

      【讨论】:

        【解决方案5】:

        这不应该工作吗?

        if(preg_match("/getPost\.php/", $_SERVER['PHP_SELF'])){
             // Access to file directly, quit..
             die();
        }
        

        【讨论】:

        • 来自手册:$_SERVER['PHP_SELF'] in a script at the address http://example.com/test.php/foo.bar would be /test.php/foo.bar.... 这并没有真正的帮助,因为它只是提供 AJAX 页面。被调用的脚本是 AJAX 页面,而不是原始请求页面。
        【解决方案6】:

        我认为您可以(至少部分)解决您的密码学问题。

        假设您有一个页面 main.php,其中包含 JS 以调用另一个名为 ajax.php 的页面。当访问页面main.php 时,使用$browserKey$salt 创建$_SESSION["tempHash"]。 (您还需要存储 salt。)然后,将向您的页面 ajax.php 发出请求的 JavaScript 提供密钥,并检查密钥和 salt 是否提供与以前相同的哈希值。在main.php 上,执行以下操作:

        <?php
        session_start();
        // authorize user here
        $salt = time();
        $browserKey = mt_rand();
        $hash = sha1("$browserKey$salt");
        $_SESSION["tempSalt"] = $salt;
        $_SESSION["tempHash"] = $hash;
        // ... code ...
        ?>
        <!doctypehtml>
        <html>
        <!-- html -->
        <script>
        // ... ajax call ...
        var params = "param1=val1&param2=val2&...&browserKey=<?= $browserKey ?>";
        request.send(params);
        </script>
        </html>
        <?php session_write_close(); ?>
        

        然后,在ajax.php 上,简单地做

        <?php
        $validated = false;
        if(sha1($_POST["browserKey"] . $_SESSION["tempSalt"]) === $_SESSION["tempHash"]) {
            $validated = true;
        }
        // and unset the salt and hash
        $_SESSION["tempSalt"] = $_SESSION["tempHash"] = null;
        if(!$validated) {
            // taken from another SO answer: 
            // http://stackoverflow.com/a/437294/2407870
            header('HTTP/1.0 404 Not Found');
            echo "<h1>404 Not Found</h1>";
            echo "The page that you have requested could not be found.";
            exit();
        }
        // else, continue normal processing here
        ?>
        

        我不是该领域的专家,所以请接受我的建议,。 (呵呵,密码学笑话。)

        这种方法的一个潜在漏洞是该人可能会加载页面main.php,然后等待五个小时并调用页面ajax.php。它仍然只允许他们访问一次。你可以做其他事情来防止这种情况发生。例如,检查盐(通过time() 获得)以确认没有经过太多时间。甚至定期向服务器发送心跳,服务器会生成新的哈希、盐和密钥,并将新密钥返回给浏览器。

        【讨论】:

          猜你喜欢
          • 2018-11-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-08-17
          • 2018-06-18
          • 1970-01-01
          • 2019-08-03
          相关资源
          最近更新 更多