是否可以将二进制图像数据放入 html 标记中,然后在任何浏览器中照常显示图像?
Posted
技术标签:
【中文标题】是否可以将二进制图像数据放入 html 标记中,然后在任何浏览器中照常显示图像?【英文标题】:Is it possible to put binary image data into html markup and then get the image displayed as usual in any browser? 【发布时间】:2011-01-26 15:51:11 【问题描述】:这是一个重要的安全问题,我相信这应该是可能的。
一个简单的例子:
您运行一个社区门户。用户注册并上传他们的照片。 只要允许显示图片,您的应用程序就会给出安全规则。比如用户必须是系统双方的好友,才能查看别人上传的图片。
问题来了:可能有人爬取了您服务器的图像目录。但您希望保护您的用户免受此类攻击。
如果可以将图像的二进制数据直接放入 html 标记中,您可以将图像目录的用户访问权限限制为用户,并将您的 Web 应用程序运行分组并将图像数据传递给您的 Apache 用户和直接在 HTML 中分组。
唯一可能的弱点是运行您的网络应用程序的用户的密码。
已经有可能了吗?
【问题讨论】:
有一种方法可以将图片短时间缓存在服务器的公共目录中,但这会使其变得昂贵。 【参考方案1】:如果我需要图像目录的安全性,我根本不会公开该目录。相反,我的 img src 属性将引用一个将用户 ID 和图像 ID 作为参数的页面。
该页面将验证该用户确实有权查看该图片。如果一切顺利,请将二进制文件发回。否则什么都不发送。
例如:
<img src="imgaccess.php?userid=1111&imgid=223423" />
另外,我不会使用可猜测的 ID。而是坚持使用 base 64 编码的 guid 之类的东西。
【讨论】:
+1,很好的答案,但是如果您的代码验证了用户的访问权限,那么 ID 是否可猜测是否重要? +1 你会怎么看待做一些 .htaccess 魔法并输出类似src="userid/user-image/"
的东西,并将其视为一个目录,锁定还是按用户解锁?
但是我在 src="" 部分有二进制数据。我会从当前会话中获取用户 ID,这样更安全。
@bmb:文件 id 并不重要。但是,它适用于成员 ID。
我很惊讶这么久了,没有人告诉你,当你在这个庄园中使用 PHP 时,你引入了本地文件包含的安全漏洞。它可能导致远程代码执行漏洞。【参考方案2】:
使用 HTML5,您可以使用 canvas 标记和 javascript 来执行此操作。
您也许可以使用 CSS 或表格布局来绘制图片(可能性能、分辨率、可移植性非常差)。
无论哪种方式,都无法阻止人们为您拍照。他们可以截取屏幕截图并将其裁剪出来。
正如克里斯在他的回答中提到的那样,拥有长图片 ID 以便每个图片的 URL 不容易被猜测或暴力破解是很重要的。您的网络服务器目录上也没有目录列表。
【讨论】:
【参考方案3】:我不确定我是否理解,但这里是。而不是提供位于图像文件夹中的静态图像 - 为什么您不能使用您选择的服务器端技术将图像动态发送到客户端?这样一来,您的服务器端代码就可以混入其中并以编程方式允许或拒绝访问?
<img src="/images/getImage.aspx?id=123353 />
【讨论】:
【参考方案4】:其他答案中描述了其他(更好的)方法来保护您的文件,但是可以将图像嵌入到您的 html 中。
这样使用<img>
标签:
<img src="data:image/gif;base64,xxxxxxxxxxxxx...">
xxxxx...
部分是 gif 图像数据的 base64 编码。
【讨论】:
所以 xxxxxxxxxx 是为 to_blob/read/to_binary 命令/为图像的二进制数据?最后必须有一个“=”吗? 您必须将二进制数据转换为 base64 编码。根据 base64 规范,结果是一串可打印字符,通常以 1 或 2 个“=”符号结尾。您需要将 xxx 替换为该字符串,全部放在一行中。 我总是使用 Windows XP 附带的标准版本运行 IE 测试 - 我想仍然有很多人使用它... 我不知道我是如何偶然发现这个老问题/答案的,但重要的是要注意这不是 binary 作为 OP提及。这是 base64 ASCII 编码。源最初是二进制的。 应该提到它们被称为数据url【参考方案5】:您可以将图片从文档根目录移到一个私有目录中,然后通过您的应用程序传递它们,该应用程序可以访问该目录。每次您的应用生成图像标签时,它还会生成一个短期安全令牌,在访问特定图像时必须指定该令牌:
<img src="/app/getImage.xyz?image=12345&token=12a342e32b321" />
很少有人会在正确的时间用正确的图像暴力破解正确的令牌。 至少有可能验证“getImage”中的令牌:
-
跟踪应用程序中的所有图像标签并将记录存储在数据库中,该数据库将随机生成的令牌和图像 ID 链接到请求用户。然后,“getImage”操作会根据该数据库检查提供的参数。
生成令牌作为校验和(MD5、CRC 等),覆盖用户 ID、图像 ID 以及可能是一年中的当前日期,并确保混入不可猜测的盐。然后,“getImage”操作将重新计算校验和,并根据指定的校验和进行检查,以验证用户的访问权限。与第一种方法相比,此方法产生的开销更少。
PHP 示例:
$token = md5($_SESSION['user_id'].' '.$imageID.' '.$SECRET_SALT.' '.date('z'));
【讨论】:
考虑到这一点,我发现将引用 HTML 页面的访问约束再次应用到上面有人写的“getImage”操作更容易。尽管如此,校验和方法可能会降低性能影响,因为它不访问任何外部资源来验证请求。 谢谢。我没有意识到我可以简单地在我的 Express 服务器中间件上解析一个查询参数名称令牌,在那里我检查了用户是否使用他们的令牌进行了身份验证......这比需要执行显式 GET 请求,然后弄清楚如何将二进制图像数据正确加载到 img HTML 标记中......这样做看起来更像是一个适当的 API / 就像谷歌地图如何要求用户向他们提供访问令牌,即。【参考方案6】:https://www.base64-image.de/
我用这个网站生成base64代码fir给定图像,然后这个网站提供代码直接粘贴。它奏效了。
【讨论】:
以上是关于是否可以将二进制图像数据放入 html 标记中,然后在任何浏览器中照常显示图像?的主要内容,如果未能解决你的问题,请参考以下文章
是否可以将来自 URL 的图像放入 android 的 imagebutton 中?