【问题标题】:Monitor image access AND/OR prevent direct access监控图像访问和/或防止直接访问
【发布时间】:2011-10-16 11:25:42
【问题描述】:

我希望用户将图像视为网页的一部分我想避免他们直接访问图像。例如,这可以在 URL 中提供有关他们链接到哪个用户的线索(我在一个 facebook 应用程序中看到的一个缺陷)。

如何监控图像访问和/或防止直接访问图像(例如通过 url 重写...)?

目前建议的解决方案:

  • 使用标头(可靠吗?)
  • 使访问图像更加困难(例如:将图像设置为 div 背景)。
  • ...

【问题讨论】:

  • 你可以检查一个referrer header;如果图像是从您的网站加载的,则引荐来源网址应该是您域上的 URL。虽然它不是万无一失的,一些广告拦截/隐私软件和代理会剥离引荐来源标头,使其看起来像直接访问,而不是。
  • 将图像作为 div 的背景 - 用户获得直接链接将更加困难(但可能)。
  • 检查referrer的方法是错误的。推荐人可以是空的,甚至可以是错误的(上一页的网址,不是当前的)。

标签: php jquery image url indirection


【解决方案1】:

没有防弹方法。但是,您可以使用启发式方法。检查以下标题:

  1. Referer -- 如果浏览器由于<img> 标签或 CSS 请求图像,则此标头将出现。如果直接请求图像(通过在地址栏中输入 URL),则此标头将为空。如果此标头包含另一个域,则该其他网站热链接您的图像。 请注意,这是预期行为,但不能保证每个浏览器都会这样。

  2. Accept -- 当请求图像时,此标头将包含诸如image/* 之类的字符串,因为浏览器发现它嵌入在 HTML 标记或 CSS 中。当有人通过在浏览器中输入直接请求图像时,您会找到诸如text/html,application/xhtml+xml 等值。这是因为浏览器在请求http://website.com/someimage 时不知道会发生什么。 jpg;因此,它最好要求text/html 内容。

在 Apache 中,您可以检查(并匹配)HTTP 标头以确定内容是否可访问。我不确定其他平台,但您可以编写一个通用代理脚本来提供图像。

编辑

如果图像 URL 显示了您不想披露的信息,您可以使用散列或加密对其进行模糊处理。因此,不要提供以下内容:

<img src="/images/users/12345.jpg">

你会写:

<img src="/images/users/image.php?hash=<?php echo md5('secret' . '12345'); ?>">

您需要编写一个脚本,将相应的图像发送到浏览器。

【讨论】:

  • because browser does not know what to expect when it requests http://website.com/someimage.jpg - 大声笑,哪个浏览器如此愚蠢以至于不读取网址中的.jpg?你关于推荐人的第一个“规则”是完全错误的。推荐人可以是空的,也可以包含另一个域......只是因为(你可以检查它)。此标头的行为非常难以预测。
  • @SalmanA:同样当你右键点击“显示图片”时,它也会“发送”referer
  • @OZ_...愚蠢的浏览器是FF4。尝试在地址栏中粘贴 this URL 并告诉我你得到了什么标题。至于推荐人,我将编辑我的答案并强调这不是防弹的;但我提到的行为是大多数情况下的预期行为。为什么不在投票前测试自己?
  • @genesis:是的。我从来没有说过防弹。
  • @Salman A 这不是expected behavior is most cases,这只是你的假设。我没有 FF4,我在 Opera 中测试了“Accept”标头,在这两种情况下,此标头都包含:Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1。在 Chrome 中:嵌入:*/*,直接:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
【解决方案2】:

如果可以的话,同样不是防弹,但很多人都会使用的东西是使用图像作为背景。在您的 HTML 中放置一个填充有特殊透明 1px x 1px gif(blank.gif circa html table layouts)的图像标记,并将其调整为实际图像的尺寸。然后将它的背景图像设置为实际图像。这将欺骗许多只知道如何右键单击以下载/获取图像 URL 的用户。

<html>
<head>
    <style>
        #logo { background: url(my-logo.png); width: 100px; height: 50px; } /* Change this to match your image name and dimensions */
    </style>
</head>
<body>
    <img src="blank.gif" id="logo">
</body>
</html>

我知道如果用户打印屏幕(但任何方法都不会),这将无济于事,但对于那些知识较少的用户来说,这是一个解决方案。另外,像 Youtube 这样的网站已经采用了这种方法,所以如果它对 Google 来说足够好,我会说它对你或我来说都足够好!

编辑:请原谅我完全没有意识到这已经被发布为评论。我在发布之前就开始写作了。

【讨论】:

    【解决方案3】:

    如前所述,这样做没有灵丹妙药(例如,您不能阻止用户进行屏幕截图)

    但是,如果你想保护你的图片免受匿名访问,你可以使用一个 php“代理”来检查用户是否可以看到该图片,然后加载它。

    这是一个非常简单的代理示例代码。 如果您真的想保护您的图像,请将它们存储在文档根目录之外。

    <?php
    
    //Sample image protection proxy. Do not use as is.
    
    //Let's monitor the authorized accesses
    session_start();
    $mon = isset($_SESSION['mon']) ? $_SESSION['mon'] : 0;
    
    
    //Let's simulate an auth mecanism
    $allowed = isset($_GET['allowed']) ? (int)$_GET['allowed'] : 0;
    
    if ($allowed === 1) {
        // DO NOT USE AS IS ! add security checks to prevent XSS, especially if images are uploaded by untrusted users
        $img = file_get_contents('img.png');
        $mon++;
        $_SESSION['mon'] = $mon;
        header('content-type:image/png');
        echo $img;
    } else {
            //handle unauthorized access here.
        //For this example, I send some plain text
        header('content-type:text/plain');
        echo 'You are not allowed to see that picture.'.PHP_EOL;
        echo 'This picture has been opened : '.$mon. ' times.'; 
    }
    ?>
    

    如果你想测试这个脚本:

    • 把它放在你的文档根目录中
    • 在同一文件夹中添加 png 图像。将此图片命名为 img.png。
    • 要访问图像,请使用http://url/of/the/script.php?allowed=1
    • 要访问计数器,请删除“允许”变量。

    希望有帮助!

    【讨论】:

      【解决方案4】:

      这是一个可能可行的想法,虽然我并没有真正考虑过太多,也没有尝试过:

      1. 服务器收到页面请求。
      2. 使用引用图像的一次性密钥 (OTK) 在 PHP 中生成页面内容。 OTK 可以存储在会话变量或数据库中。
      3. 当客户端呈现页面时,服务器使用 OTK 通过图像查询参数接收请求。提供图片并删除 OTK。

      例如,而不是:

      &lt;img src="www.mysite.com/mypage/myimage.jpg"&gt;

      ...生成一次性密钥并将其存储在查找表中,以便它引用您的图像:

      4e33fd162fe95 =&gt; image.jpg

      ...然后使用该 OTK 生成您的页面:

      &lt;img src="www.mysite.com/mypage?image=4e33fd162fe95"&gt;

      当服务器收到对该图像的请求时,发送图像并删除 OTK。这意味着对页面的每个请求都会生成一个新的 OTK。再次尝试对该图像使用该 URI 将不起作用。

      这在性能方面有一些明显的警告,因为客户端缓存将不再起作用,并且会给服务器带来一些开销。可能还有其他警告。

      【讨论】:

        猜你喜欢
        • 2011-04-28
        • 2016-06-28
        • 2023-02-16
        • 2012-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多