ZF2:如何将安全图像作为网页的一部分提供服务

Kim*_*nce 0 php image-processing zend-framework2

我已经构建了一个包含用户个人资料的 ZF2 应用程序,现在我希望允许用户上传并显示他们的照片作为其个人资料的一部分。就像您在 LinkedIn 中看到的那样。

上传照片似乎很容易(使用Zend\InputFilter\FileInput())。我的那个工作得很好。

在我看来,将它们存储在网络根目录之外很有意义。(例如,我不需要担心用户在目录上使用 wget )。但是如何将这些图像嵌入到网页中呢?

如果它们位于网络根目录内,我会简单地执行此操作<img width="140" src="/img/filename.jpg">,但显然,如果它们位于安全位置,则这是不可能的。解决办法是什么?

Jac*_*din 5

你说得对。Web 开发人员传统上会混淆用于存储图像的路径,以防止恶意个人批量检索它们(正如您在wget评论中提到的那样)。

\n\n

因此,虽然存储用户的头像/uploads/users/{id}.jpg很简单(并且不一定不合适,具体取决于您的用例),但您可以使用方法来混淆 URL。请记住:有两种方法可以解决该问题。

\n\n

更简单地说,您希望确保无法根据“公共”信息(例如用户的主键)确定资产 URL。因此,如果用户的用户 ID 为 37,访问其头像将不会像下载/uploads/users/37.jpg.

\n\n

一种更有力的方法是确保人们无法将 URL 与其公共信息相关联。像这样的 URL/uploads/users/37/this-is-some-gibberish.jpg将其所有权“显示”;该内容的负责人必须是ID为37的用户。

\n\n

一个简单的解决方案

\n\n

如果您想采用更简单的方法,请根据设置的属性(例如用户的 ID)和应用程序范围的盐生成快速哈希。对于 PHP,请查看“非加密用途的最快哈希?”

\n\n
$salt = \'abc123\'; // Change this, keep it secret, store it as env. variable\n$user->id; // 37\n$hash = crc32($salt . strval($user->id)); // 1202873758\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在我们有了一个唯一的哈希值,可以将文件存储在这个端点:/uploads/users/37/1202873758.jpg。每当我们需要引用用户的头像时,我们都可以重复此逻辑来生成创建文件名所需的哈希值。

\n\n

碰撞问题

\n\n

您可能想知道,为什么我不能将其存储在/uploads/users/1202873758.jpg?这不会保证我的用户身份安全吗?(如果您不好奇,那没关系,我会向其他读者解释。)我们可以,但生成的哈希值不是唯一的;如果用户数量足够多,我们将用其他用户的头像覆盖该文件,从而使我们的存储解决方案变得无能为力。

\n\n

为了更加隐秘

\n\n

公平地说,/uploads/users/1202873758.jpg这是一个更隐秘的文件名。也许甚至/uploads/1202873758.jpg会更好。用这样的路径存储文件;我们需要确保唯一性,这不仅需要生成哈希,还需要检查唯一性,适应不可避免的冲突,并存储(可能修改的)哈希\xe2\x80\x94以及能够从存储中检索哈希如所须。

\n\n

根据您的应用程序堆栈,您可以通过无数种方式来实现这一点,根据您的需求,有些方式比其他方式更适合,所以我不会在这里深入讨论。

\n