使用 PHP 保护文档
我有一个简单的登录/访问控制系统来保护一些受限制的页面,但在这些页面内有一些需要保护的链接,即Word文档。因此,如果我将这些资源保留在 webroot 中,它们就可以通过 URL 访问。保护受限制页面内的这些资源的最佳方法是什么?我知道我可以用密码保护该文件夹,但用户会受到两次挑战,一次针对受限页面,另一次针对资源链接。有什么建议吗?
I have a simple login / access control system to secure some restricted pages, but within these pages there are links that need to be secure, i.e. Word documents. Therefore if I keep these resources within the webroot they could accessible via a URL. What is the best method to secure these resources that are within the restricted page. I know I could password protect the folder but the user would then be challenged twice, one for the restricted page and then for the resource link. Any advice ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
更多
发布评论
评论(2)
根据您的用例,您在这里有几个选项。
使用 PHP 来提供文件。基本上,要么拦截 PHP 读取文件的所有尝试(使用 mod_rewrite 规则),要么直接链接到 PHP 并将文件放在文档根目录下。然后使用类似
fpassthru
将文件发送到浏览器。请注意,您必须正确设置内容类型标头。另请注意,这会占用大量服务器资源,因为服务器需要用 PHP 读取整个文件并发送它,所以这很容易,但并不轻松。这样做的主要好处是它简单且可移植(适用于所有服务器)。但是,您正在牺牲宝贵的服务器资源(因为当 PHP 提供文件服务时,它无法提供其他页面服务)来换取这一好处...
使用 Web 服务器通过类似
X-SendFile
(Lighttpd),X-SendFile
(Apache2/2.2) 或 <代码>X-Accel-Redirect (NginX)。因此,您可以将对文件的所有请求重定向到 PHP(手动或重写)。在 PHP 中,您需要进行身份验证。您需要发送 Content-Type 标头,然后发送类似X-SendFile: /foo/file.doc
的标头。服务器实际上会发送文件,因此您不必这样做(它比从 PHP 本机发送效率远高效)。这里的主要好处是您不需要从 PHP 提供文件。您仍然可以执行您想要的所有身份验证和日志记录,但在开始传输文件后立即释放 PHP。
使用类似
mod_secdownload
(lighttpd) 或mod_auth_token
(Apache)。基本上,当您生成文件的链接时,您会在 PHP 中创建一个令牌。该令牌是秘密密码的 MD5 与当前时间戳的组合。这样做的好处是 URL 仅在您在配置中指定的时间内有效(默认情况下为 60 秒)。因此,这意味着您给出的链接只会有效 60 秒,然后任何进一步尝试查看内容都会生成 400 系列错误(我不确定这是我的想法)。这样做的主要好处是与实现相关的开销非常少。但您必须适应 URL 仅在设定时间内有效(默认为 60 秒)...
将其推送到 CDN 上进行处理。这类似于选项 #3(上面的选项),但使用 CDN 来处理文件服务而不是本地服务器。某些 CDN(例如 EdgeCast)提供类似的功能,您可以在其中设置令牌,该令牌将在设定的时间后过期。如果您有大量流量并且可以证明 CDN 费用合理,那么这种情况会很好地发挥作用。 (注意:与链接的 CDN 没有任何关系,仅链接是因为我知道它们提供该功能)。
就我个人而言,我已经完成了上述所有操作。您的用例是什么确实很重要。如果您正在构建一个将安装在共享主机或您无法控制的多个不同服务器上的系统,请坚持使用第一个选项。如果您拥有完全控制权并且需要节省服务器资源,请执行其他两项之一。
注意:除了这三个之外还有其他选项。这些只是最容易实现的,大多数其他选项与这些选项足够相似,可以归入该类别......
You have a few options here, depending on your use-case.
Use PHP to serve the file. Basically, either intercept all attempts to read the file by PHP (using a mod_rewrite rule), or link directly to PHP and put the file(s) below the document root. Then use something like
fpassthru
to send the file to the browser. Note that you must properly set the content-type headers. Also note that this will eat up a lot of server resources since the server needs to read the entire file in PHP and send it, so it's easy, but not light.The main benefit to doing it this way is that it's easy and portable (will work on all servers). But you're trading off valuable server resources (since while PHP is serving the file, it can't be serving another page) for that benefit...
Use the web-server to send the file using something like
X-SendFile
(Lighttpd),X-SendFile
(Apache2/2.2) orX-Accel-Redirect
(NginX). So you'd redirect all requests to the file to PHP (either manually or rewrite). In PHP you'd do your authentication. You'd send the Content-Type headers, and then send a header likeX-SendFile: /foo/file.doc
. The server will actually send the file, so you don't have to (it's far more efficient than sending from PHP natively).The main benefit here is that you don't need to serve the file from PHP. You can still do all of your authentication and logging that you'd like, but free up PHP as soon as you start transferring the file.
Use something like
mod_secdownload
(lighttpd) ormod_auth_token
(Apache). Basically, you create a token in PHP when you generate the link to the file. This token is a combination of a MD5 of a secret password combined with the current timestamp. The benefit here, is the URL is only valid for how long you specify in the configuration (60 seconds by default). So that means that the link you give out will only be active for 60 seconds, and then any further attempts to see the content will generate a 400 series error (I'm not positive which off the top of my head).The main benefit to doing it this way is that there is very little overhead associated with the implementation. But you have to be comfortable with having URLs being valid for a set time only (60 seconds by default)...
Push it off onto a CDN to handle. This is like option #3 (the one above), but uses a CDN to handle the file serving instead of your local server. Some CDNs such as EdgeCast provide a similar functionality where you set a token which expires after a set amount of time. This case will work nicely if you have a lot of traffic and can justify the expense of a CDN. (Note: no affiliation with the linked CDN, only linked because I know they offer the functionality).
As far as how I'd personally do it, I've done all of the above. It really matters what your use-case is. If you're building a system that's going to be installed on shared hosts or multiple different servers which you don't control, stick to the first option. If you have full control and need to save server resources, do one of the other two.
Note: there are other options than these three. These are just the easiest to implement, and most of the other options are similar enough to these to fit into the category...
我还没有尝试过使用Word文档(仅使用图像),但我会尝试直接从php提供文档,查看我关于图像的回答。
它类似于链接到 php 页面的
a
标记,该页面以 Word 文档作为其内容类型。I haven´t tried it with word documents (only with images), but I would try to serve the document directly from php, see my answer about images.
It would be something like an
a
tag linking to a php page that serves a Word document as its content type.