我希望用户将图像视为网页的一部分,但我想避免他们直接访问图像。例如,这可以在 URL 中提供有关他们链接到哪个用户的线索(我在一个 facebook 应用程序中看到的一个缺陷)。
如何监控图像访问和/或防止直接访问图像(例如通过 url 重写......)?
到目前为止建议的解决方案:
- 使用标头(可靠吗?)
- 使访问图像更加困难(例如:将图像设置为 div 背景)。
- ...
我希望用户将图像视为网页的一部分,但我想避免他们直接访问图像。例如,这可以在 URL 中提供有关他们链接到哪个用户的线索(我在一个 facebook 应用程序中看到的一个缺陷)。
如何监控图像访问和/或防止直接访问图像(例如通过 url 重写......)?
到目前为止建议的解决方案:
没有防弹方法。但是,您可以使用启发式方法。检查以下标题:
Referer
<img>
-- 如果浏览器通过标签或 CSS请求图像,则此标头将出现。如果直接请求图像(通过在地址栏中输入 URL),则此标头将为空。如果此标头包含另一个域,则该其他网站热链接您的图像。请注意,这是预期的行为,但不能保证每个浏览器都会以这种方式运行。
Accept
-- 这个标头将包含一个字符串,例如image/*
何时请求图像,因为浏览器发现它嵌入在 HTML 标记或 CSS 中。当有人通过在浏览器中直接输入请求图像时,您会找到诸如 etc 之类的值。这是因为浏览器在请求http://website.com/someimage.jpgtext/html,application/xhtml+xml
时不知道会发生什么;因此它最好要求内容。text/html
在 Apache 中,您可以检查(并匹配)HTTP 标头以确定内容是否可访问。我不确定其他平台,但您可以编写一个通用代理脚本来提供图像。
如果图像 URL 显示了您不想公开的信息,您可以使用散列或加密对其进行模糊处理。因此,不要提供以下内容:
<img src="/images/users/12345.jpg">
你会写:
<img src="/images/users/image.php?hash=<?php echo md5('secret' . '12345'); ?>">
您需要编写一个脚本,将相应的图像发送到浏览器。
如果可以的话,同样不是防弹的东西,但很多人都会使用图像作为背景。在您的 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 这样的网站已经采用了这种方法,所以如果它对谷歌来说足够好,我会说它对你或我来说已经足够好了!
编辑:请原谅我完全没有意识到这已经被发布为评论。我在发布之前就开始写作了。
如前所述,这样做没有灵丹妙药(例如,您不能阻止用户进行屏幕截图)
但是,如果你想保护你的图片免受匿名访问,你可以使用一个 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.';
}
?>
如果你想测试这个脚本:
希望有帮助!
这是一个可能可行的想法,尽管我并没有真正考虑过太多,也没有尝试过:
例如,而不是:
<img src="www.mysite.com/mypage/myimage.jpg">
...生成一次性密钥并将其存储在查找表中,以便它引用您的图像:
4e33fd162fe95 => image.jpg
...然后使用该 OTK 生成您的页面:
<img src="www.mysite.com/mypage?image=4e33fd162fe95">
当服务器收到对该图像的请求时,发送图像并删除 OTK。这意味着对页面的每个请求都会生成一个新的 OTK。再次尝试对该图像使用该 URI 将不起作用。
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.