监视图像访问和/或防止直接访问

发布于 2024-11-27 08:25:58 字数 268 浏览 0 评论 0原文

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

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

到目前为止建议的解决方案:

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

I want users to see an image as part of a web page but I want to avoid them accessing a image directly. This could, say, give clues in the URL about what user they're linked to (a flaw I've seen in one facebook application).

How can I go about monitoring image access and/or preventing direct access to images (through url rewriting for example...)?

Solutions suggested so far:

  • Use of headers (reliable?)
  • Making access to images more difficult (ex: set image as div background).
  • ...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

美人如玉 2024-12-04 08:25:58

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

  1. Referer -- 当浏览器由于 标记或 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'); ?>">

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

There is not bullet proof way. However, you can use heuristics. Inspect the following headers:

  1. Referer -- this header will be present is the image was requested by the browser as a result of <img> tag or CSS. This header will be empty if the image was requested directly (by typing the URL in address bar). If this header contains another domain then that other website hot-linked your image. Note that this is the expected behavior but it is not guaranteed that every browser will behave this way.

  2. Accept -- this header will contain a string such as image/* when image was requested because browser found it embedded in HTML tags or CSS. When someone requests the image directly by typing in the browser, you'll find values such as text/html,application/xhtml+xml etc. This is because browser does not know what to expect when it requests http://website.com/someimage.jpg; hence it will preferably ask for text/html content.

In Apache, you can check (and match) HTTP headers to determine whether content is accessible or not. I am not sure about other platforms, but you can write a generic proxy script for serving images.

Edit

If the image URL reveals information that you do not want disclosed, you can obfuscate it by using hashes or encryption. So instead of serving content such as:

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

You will write:

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

You'll need to write a script that sends the corresponding image to the browser.

池木 2024-12-04 08:25:58

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

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

例如,而不是:

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

4e33fd162fe95 => image.jpg

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

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

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

Here's an idea that may work, although I've not really thought it through too much, and haven't tried it:

  1. Server receives a request for a page.
  2. Generate page content in PHP, using a one-time-key (OTK) that refers to the image. The OTK could be stored in a session variable or a database.
  3. When the client renders the page, the server receives a request via a query parameter for the image, using the OTK. Supply the image and delete the OTK.

For example, instead of:

<img src="www.mysite.com/mypage/myimage.jpg">

...generate a one-time-key and store that in a lookup table, so that it refers to your image:

4e33fd162fe95 => image.jpg

...then generate your page using that OTK instead:

<img src="www.mysite.com/mypage?image=4e33fd162fe95">

When the server receives a request for that image, send the image, and delete the OTK. This means that every request for the page generates a new OTK. Trying to use that URI for the image again will not work.

This has some obvious caveats in terms of performance, as client-side caching would no longer work, and it will place some overhead on the server. There are probably other caveats too.

许一世地老天荒 2024-12-04 08:25:58

如果可以的话,我再说一遍,虽然不是万无一失,但有很多技巧,那就是使用图像作为背景。在 HTML 中放置一个图像标签,其中填充了特殊的透明 1px x 1px gif(blank.gif circa html 表格布局),并将其调整为实际图像的尺寸。然后将其背景图像设置为实际图像。这会欺骗许多只知道如何右键单击下载/获取图像 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 来说足够好,我会说它对你或我来说也足够好!

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

If I may, something that again isn't bullet-proof, but tricks many is to use the image as a background. In your HTML place an image tag filled with a special transparent 1px by 1px gif (blank.gif circa html table layouts) and size it to the dimensions of your actual image. Then set the background image of it to be the actual image. This will trick many users who only know how to right click to download/get the URL of an image.

<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>

I know this won't help if the user Print Screens (but neither will any method), but it is a solution for those less knowledgeable users. Plus, sites like Youtube already employ this method so if it's good enough for Google, I'd say it's good enough for you or me!

EDIT: Please excuse my total lack of consciousness to this already being posted as a comment. I began writing before that was posted.

鸠魁 2024-12-04 08:25:58

如前所述,执行此操作没有灵丹妙药(例如,您无法阻止用户进行屏幕截图)

但是,如果您想保护您的图片免受匿名访问,您可以使用 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
  • 要访问计数器,请删除“允许”变量。

希望有帮助!

As said, there is not silver bullet for doing this (you can't prevent the user to make a screen capture for example)

But, if you want to protect your pictures against anonymous access, you can use a php "proxy" that will check if the user is allowed to see that pic, and then load it.

Here is a very simple sample code for such a proxy.
If you really want to protect your images store them outside your document root.

<?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.'; 
}
?>

If you want to test this script :

  • put it somewhere in your docroot
  • add a png image in the same folder. Name this image img.png.
  • to access the image, use http://url/of/the/script.php?allowed=1
  • to access the counter, remove the 'allowed' var.

Hope that helps !

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文