【问题标题】:Storing and reading images above public_html在 public_html 之上存储和读取图像
【发布时间】:2010-11-27 19:24:30
【问题描述】:

我正在尝试保护我的 PHP 图像上传脚本,我必须跳过的最后一个障碍是让用户无法直接执行图像,但服务器仍然可以在网页中提供它们。我尝试更改文件夹的所有权和权限无济于事,因此我尝试将图像存储在 public_html 之上并将它们显示在存储在 public_html 中的页面中。

我的文件结构:

 - userimages
   image.jpg
   image2.jpg

 - public_html
   filetoserveimage.html

我尝试像这样链接到 userimages 文件夹中的图像:

<img src="../userimages/image.jpg">

但它不起作用。我在这里缺少什么吗?如果您有更好的建议,请告诉我。我试图阻止公共用户执行他们可能已上传的潜在危险文件。就像一个额外的安全措施。谢谢!

【问题讨论】:

    标签: php html security filesystems


    【解决方案1】:

    你想要的东西基本上是不可能的。

    浏览器加载页面的方式(在非常基本的意义上)是这样的:

    第 1 步:下载页面。 第二步:解析页面。 第 3 步:下载页面内容中引用的任何内容(图像、样式表、javascript 等)

    每个“下载”事件都是原子的。

    您似乎只想向刚刚下载引用这些图片的页面的人提供图片。

    如 PHP Jedi 所示,您可以通过 PHP 传递文件。您可以扩展他的代码,并检查请求中的 HTTP_REFERER,以确保人们不会“仅”抓取图像。

    现在,通过 PHP passthru 脚本为每个图像提供服务效率不高,但它可以工作。

    人们想要这样做的最常见原因是避免“盗链”——当人们在引用您服务器上的图像的其他网站上创建图像标签时。当他们这样做时,您会花费资源来处理出现在其他人页面上的请求。

    如果这是您真正想要避免的,您可以使用 mod_rewrite 来检查引用者。

    可以在here找到一个不错的关于盗链/反盗链的讨论

    【讨论】:

      【解决方案2】:

      使用图像中继脚本!

      要提供位于 public_html 文件夹之外的图像文件,您必须通过 php 脚本来完成。例如,制作一个 image-relay.php 来读取公共 html 之外的图像...

      <?php
      header('Content-Type: image/jpeg');
      $_file = 'myimage.jpg'; // or $_GET['img']
      echo file_get_contents('/myimages/'.$_file);
      ?>
      

      现在,$_file 可以是一个 $_GET 参数,但它对于验证输入参数绝对很重要...

      现在您可以创建&lt;img src="image-relay.php?img=flower.jpg"&gt; 来访问位于 /myimage/flower.jpg 中的flower.jpg 图像...

      【讨论】:

      • 我不想通过提供大量图像和运行 PHP 脚本来超载 PHP。您认为这会在访问者众多的网站上造成问题吗?例如 10k 天
      • 根据我自己的经验,这会导致几个问题,特别是如果其他网站或访问者拉出太多图片,这可能会导致图像过载/拒绝。
      【解决方案3】:

      好吧,网络浏览器只能访问 public_html 中的文件和文件夹。

      【讨论】:

        【解决方案4】:

        如果public_html 目录是您用户的服务器的根目录,则 Apache 无法提供不在该目录内部/之下的任何内容。

        如果您希望 Apache 直接提供文件,则必须将其放入/低于 public_html

        【讨论】:

        • 我怎样才能做到只有apache才能提供存储在public_html文件夹中的文件?
        • Heu... 实际上,如果 Apache 可以为文件提供服务,那么几乎就是这样:它可以提供文件——任何人都可以访问它们。
        【解决方案5】:

        我认为您的误解在于,如果您在 &lt;img&gt; 标记中包含图像,您的浏览器将向网络服务器发送完全相同的请求以获取它,如果您尝试将其发送到网络服务器直接在浏览器中打开图片的src url。

        因此,要么两者都起作用,要么都不起作用。

        有一些黑客攻击,涉及(php 或其他)脚本,以确保请求图像的 IP 在过去几秒钟内也请求了 html 页面(如果用户在代理后面,这将不起作用轮换传出 IP)或通过检查引荐来源网址(这不适用于 HTTPs,如果用户禁用了引荐来源网址也无效)。

        如果您想确保只有某些用户可以看到图像(通过&lt;img&gt; 标签和直接),您可以将图像放在 public_html 之外并有一个(php 或其他)脚本在之前验证用户的凭据提供图片。

        【讨论】:

          【解决方案6】:

          如果您使用的是 Apache 或 lighttpd,您可以使用 X-Sendfile 标头发送不在 Web 根目录中的文件(前提是您没有更改 mod_xsendfile 的配置)。

          要了解有关 X-sendfile 的更多信息,请参阅site

          此解决方案为您提供最佳性能,因为 PHP 不会发送文件,但服务器会发送,因此可以在提供文件时退出 PHP。

          希望对您有所帮助。

          【讨论】:

          • 现在这是一个漂亮的模块。但我想知道与 readfile() 相比(如果可能,它还使用内存映射文件)的优势有多大。
          • 首先,对于较大的文件,您可以在最大执行时间后获得 PHP 超时。此外,如果文件大于 PHP 可以分配的内存,这也不适用于 readfile(),因为 readfile 会将整个文件读入内存。我知道这不是提供图像时的主要问题,但您仍然拥有内存优势。
          猜你喜欢
          • 2019-06-11
          • 2012-01-30
          • 2018-09-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-03
          • 2012-04-28
          • 2015-04-18
          相关资源
          最近更新 更多