以性能为导向的方式来保护PHP级别的文件?

我正在寻找一些我一直在思考的东西。 这是一个非常普遍的问题,也许有解决scheme,我还没有想到。

我有一个基于PHP的CMS。
对于在CMS中创build的每个页面,用户可以上传资产(要下载的文件,图像等)

这些资产存储在一个目录中,我们称之为“/ myproject / assets”,每页为基础(1个子目录= 1页,例如“/ myproject / assets / page19283”)

用户可以在CMS中“取消”(隐藏)页面。 当一个页面被隐藏,有人试图访问它,因为他们已经记住了url,或者他们来自谷歌或其他什么东西,他们会得到一个“找不到”的消息。

但是,资产仍然可用。 我也想保护这些,以便当用户取消发布一个页面,他们可以相信它完全消失了。 (对司法麻烦非常重要,比如法院命令将内容下载…可能会发生这样的事情)。

最明显的方法是将所有资源存储在一个安全的目录 (= Web服务器无法访问)中,并使用PHP“front gate”在检查后通过文件。 当一个项目需要水密,这是我目前的方式,但我不喜欢它,因为PHP解释器运行在网站上的每一个微小的图像,脚本和样式表。 我想有一个更快的方法。

.htaccess保护(全部或类似拒绝)并不完美,因为CMS应该是可移植的,并且能够在共享环境中运行。 我希望它甚至可以在IIS和其他Web服务器上运行。

我现在可以想到的最好的方法是特定页面的资产目录移到安全的位置,并在发布时将其移回。 但是,pipe理员用户需要能够看到页面,即使它没有发布,所以我将不得不解决这个事实,我必须从安全目录提供这些资产。

任何人都可以想到一种方法,允许Apache直接访问文件(=不通过PHP脚本),但仍然使用PHP控制访问? 我不能。

我还会考虑一个简单的.htaccess解决scheme,可能在大多数共享环境中运行。

编辑:如何混合管理界面? 在ACP中,您可以通过PHP方法访问基本上将所有文件请求发送到PHP authing文件,但对于公共,您可以使用HTTP AUTH / htaccess来确定结果的可用性。 这给你在公共方面的表现,但在ACP方面的​​保护。

旧消息:

当使用mod_rewrite类型操作时.htaccess与大多数Apache和IIS <7环境(使用各种ISAPI模块)兼容。 唯一的例外是IIS7 +使用web.config文件的新Rewrite模块。 然而,我愿意你可以有效地生成/改变这个实例的web.config文件,而不是使用.htaccess。

鉴于此,您可以使用重写方法设置重定向,并重定向到您的自定义404页面(希望发送正确的404页眉)。 这不是100%合适的,因为实际的资产应该是给出403头的那个,但是…起作用。

除非要为每个服务器平台正确创建HTTP AUTH设置,否则这将是我要走的路线。 另外,如果你做得对,你或者你的用户可以使你的系统扩展到允许其他类型(包括一个基于php的选项,如果他们想做的话)。

任何敏感的东西都应该存储在你所建议的安全区域。

如果您的网站位于/ var / www / public_html

您将资源置于/ var / www / assets之外的Web访问区域之外PHP可以调用下载,或者您可以根据需要通过PHP提供文件。

如果您将HTML保留在CMS数据库中,那只会留下不敏感的图像和CSS。

如果您绝对必须打开和关闭所有材料的访问权限,我认为您最好的选择可能是符号链接。 将所有内容保存在非Web可访问区域,并将每个资源文件夹链接到Web区域。 这样,如果您需要将人员完全锁定,只需删除符号链接而不是删除所有文件。

我不喜欢它,但这是我能想到的唯一符合你的理想的东西。

我只是防止任何非HTML文件的盗链 ,所以所有的“资产”的东西只能从HTML页面访问。 删除(或保护)页面只是删除了一切,而不必搞乱整个文件系统。

我假设“页面”由PHP生成,“资产”不应该要求PHP。 (如果我弄错了,请告诉我。)

您可以重命名资产文件夹。 例如,将“/ myproject / assets / page19283”重命名为“/ myproject / assets / page19283-hidden”。 这将打破所有旧的,记忆的链接。 当您为可以看到的管理员用户生成页面时,只需使用新的文件夹名称来编写URL。 毕竟,你知道页面是否“隐藏”。 如果您知道“秘密”网址,资源可以直接访问。

为了提高安全性,请使用一堆随机文本重命名文件夹,并将其存储在页表(无论您存储隐藏标志的位置):'/ myproject / assets / page19283-78dbf76B&76daz1920bfisd6g&dsag'。 这将使得更难猜测隐藏的网址。

只需在数据库中的页面名称和文件系统中的资源目录中添加或附加一个GUID即可。 管理员将仍然可以从管理界面查看它,因为链接将被更新,但GUID有效地使页面无法被外部用户或搜索引擎发现。

将您的信息存储在Web根目录之外的目录(即:public_html或htdocs之外的一个目录)。 然后,使用php脚本中的readfile操作符在请求时代理这些文件。 readfile(…)基本上只有一个参数 – 文件的路径 – 并打印该文件的内容。

这样,您可以创建一个屏障,如果访问者请求隐藏在代理之后的信息,即使他们“记住”了URL,也可以使用404或403来关闭它们。

使用X-Sendfile

最好和最有效的方法是使用X-Sendfile。 但是,在使用X-Sendfile之前,您需要在您的网络服务器上进行安装和配置。

如何做到这一点的方法将取决于您正在使用的Web服务器,所以请查找您的特定服务器的说明。 应该只是几个步骤来实施。 一旦实施,不要忘记重新启动您的Web服务器。

一旦安装了X-Sendfile,你的PHP脚本将只需要检查登录的用户,然后提供文件。 下面是一个使用Sessions的非常简单的例子:

session_start(); if (empty($_SESSION['user_id'])){ exit; } $file = "/path/to/secret/file.zip"; $download_name = basename($file); header("X-Sendfile: $file"); header("Content-type: application/octet-stream"); header('Content-Disposition: attachment; filename="' . $download_name . '"'); 

重要的提示:

如果您想从其他网页(如图像src值)提供文件,则需要确保清理文件名。 你不希望任何人重写你的脚本,并使用“..”等来访问你的系统上的任何文件。

因此,如果您的代码如下所示:

<img src="myscript.php?file=myfile.jpg">

那么你会想要做这样的事情:

 session_start(); if (empty($_SESSION['user_id'])){ exit; } $file = preg_replace('/[^-a-zA-Z0-9_\.]/', '', $_GET['file']); $download_name = basename($file); header("X-Sendfile: $file"); header("Content-type: application/octet-stream"); header('Content-Disposition: attachment; filename="' . $download_name . '"'); 

我会去执行一个网关。 您将.htaccess文件设置为指向gateway.php脚本的/ assets / URL,该脚本将拒绝两个凭证无效且此特定文件未发布或显示。

我有点困惑。 你是否也需要保护样式表文件和图像? 也许移动这个文件夹是最好的选择。