【问题标题】:Converting a filepath to a url securely and reliably安全可靠地将文件路径转换为 ​​url
【发布时间】:2026-02-22 10:10:02
【问题描述】:

我正在使用 php,我有以下代码将绝对路径转换为 ​​url。

function make_url($path, $secure = false){
    return (!$secure ? 'http://' : 'https://').str_replace($_SERVER['DOCUMENT_ROOT'], $_SERVER['HTTP_HOST'], $path);
}

我的问题基本上是,在位置和服务器之间可移植的安全性/可靠性方面,有没有更好的方法来做到这一点?

【问题讨论】:

    标签: php security url robustness


    【解决方案1】:

    HTTP_HOST variable is not a reliable or secure value 也是由客户端发送的。所以在使用它之前一定要验证它的值。

    【讨论】:

      【解决方案2】:

      我不认为安全性会受到影响,仅仅因为这是一个 url,被打印到浏览器......可能发生的最糟糕的情况是暴露文件的完整目录路径,并可能创建一个损坏的链接。

      作为一个小旁注,如果这是在 HTML 文档中打印的,我认为您正在通过 htmlentities 之类的东西传递输出......以防万一输入 $path 包含类似 [script] 标记( XSS)。

      不过,为了让它更可靠一点,我不建议在“DOCUMENT_ROOT”上进行匹配,因为有时它要么未设置,要么不匹配(例如,当 Apache 重写规则开始妨碍时)。

      如果我要重写它,我会简单地确保始终打印“HTTP_HOST”...

      function make_url($path, $secure = false){
          return (!$secure ? 'http://' : 'https://').$_SERVER['HTTP_HOST'].str_replace($_SERVER['DOCUMENT_ROOT'], '', $path);
      }
      

      ...如果可能的话,更新调用代码以便它只通过路径,所以我什至不需要考虑删除“DOCUMENT_ROOT”(即如果路径与“DOCUMENT_ROOT”不匹配会发生什么情况)...

      function make_url($path, $secure = false){
          return (!$secure ? 'http://' : 'https://').$_SERVER['HTTP_HOST'].$path;
      }
      

      这确实留下了问题......为什么有这个功能?

      在我的网站上,我只是在脚本执行开始时定义了一个变量,它设置:

      $GLOBALS['webDomain'] = 'http://' . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '');
      $GLOBALS['webDomainSSL'] = $GLOBALS['webDomain'];
      

      我在哪里使用 GLOBALS,因此可以在任何地方访问它(例如在函数中)...但您可能还想考虑制作一个常量(定义),如果您知道这个值不会改变(我有时会改变这些值稍后在站点范围的配置文件中,例如,如果我有该网站的 HTTPS/SSL 证书)。

      【讨论】:

        【解决方案3】:

        我认为这是错误的方法。

        HTML 中的 URL 支持相对位置。也就是说,您可以使用<A href="filename.php">link</a> 来引用其URL 中与当前页面具有相同路径的页面。您也可以通过<a href="/dir/filename.php">link</a> 提供指向同一网站的完整路径。这两个技巧意味着您的网站代码实际上并不需要知道它在哪里提供有效的 URL。

        也就是说,您可能需要一些技巧,以便在http://www.example.com/dev/site.php 上拥有一个网站,在http://www.example.com/testing/site.php 上拥有另一个网站。您需要一些代码来确定正在使用哪个目录前缀,但您可以使用配置值来执行此操作。我的意思是属于该(子)站点配置的值,而不是版本控制代码!

        【讨论】: