php 在 Web 服务器中存储文件的安全方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4603901/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Secure way to store files in web server?
提问by brainless
I want my files to be secure in my web server. Only authenticated users to access those files should be able to access those files. I thought of storing files in database as "Long BLOB" but it supports only upto 2MB of data. The file size may exceed beyond 50MB. is there any other better way to secure the files? please help me.thanks in advance.
我希望我的文件在我的网络服务器中是安全的。只有访问这些文件的经过身份验证的用户才能访问这些文件。我想将数据库中的文件存储为“Long BLOB”,但它最多只支持 2MB 的数据。文件大小可能超过 50MB。还有其他更好的方法来保护文件吗?请帮助我。在此先感谢。
回答by moinudin
Don't store them in a database. Put them in your web directory and secure them using .htaccess
.
不要将它们存储在数据库中。将它们放在您的 Web 目录中并使用.htaccess
.
If you want to authenticate via other means, then store the files in a directory that isn't web-accessible but is readable by the user php runs as.
如果您想通过其他方式进行身份验证,请将文件存储在一个无法通过网络访问但用户 php 运行时可以读取的目录中。
回答by Anthony Rutledge
Discussion
讨论
If you opt to keep high value downloadable content files directly on the filesystem, the best thing to do is to keep them outside of the webroot. Then, your application will have to solve the problem of creating URLs (url encoding when necessary) for content (PDF's, Word Docs, Songs, etc..).
如果您选择直接在文件系统上保留高价值的可下载内容文件,最好的做法是将它们保留在webroot之外。然后,您的应用程序必须解决为内容(PDF、Word 文档、歌曲等)创建 URL(必要时进行 url 编码)的问题。
Generally, this can be achieved by using a query to retrieve the file path, then using the file path to send content to the user (with header()
etc ..) when he or she clicks on an anchor (all of this without the user ever seeing the true, server side file path).
通常,这可以通过使用查询来检索文件路径,然后在用户header()
单击锚点时使用文件路径将内容发送给用户(使用等...)来实现(所有这些都没有用户看到)真正的服务器端文件路径)。
If you do not want user Asharing URLs for high value downloadable content to user B, then your application must somehow make the links exclusively tied to user A. What can be done? Where should I start?
如果你不希望用户一个高价值的下载内容到用户共享的网址乙,那么你的应用程序必须以某种方式使完全依赖于用户的链接一个。可以做什么?我应该从哪里开始?
Obviously, you want to make sure user Ais logged in during a session before he or she can download a file. What is not so obviousis how to prevent a logged inuser Bfrom using a URL sent from user A(to user B) to download A'sdigital content.
显然,您要确保用户A在会话期间已登录,然后他或她才能下载文件。什么是不那么明显的是如何防止一个登录用户乙使用从用户发送的URL一个(用户乙)下载A的数字内容。
Using $_SESSION
to store the logged in user's ID (numerical, or string) and making that part of the eventual query (assuming content is tied to user purchases or something) will prevent a logged in user Bfrom downloading things they have not purchased, but you will still incur the resource hit for processing the SQL empty set for items they have not purchased. This sounds like a good step two.
使用$_SESSION
存储的登录用户的ID(数字或字符串),使最终的查询部分(假设内容被绑定到用户购买或东西)将防止登录的用户乙从网上下载他们没有东西买,但你仍然会导致资源命中来处理他们尚未购买的项目的 SQL 空集。这听起来是很好的第二步。
What about step one? Is there something that can prevent the need to do a query to begin with?
第一步呢?有什么可以阻止需要做一个查询开始?
Well, let us see. In HTML forms, one might use a XSRF token in a hidden field to verify that a submitted form actually originated from the web server that receives the POST/GET request. One token is used for the entire form.
好吧,让我们看看。在 HTML 表单中,可以在隐藏字段中使用 XSRF 令牌来验证提交的表单实际上来自接收 POST/GET 请求的 Web 服务器。一个令牌用于整个表单。
Given a page of user specific things to download (anchors), one could embed a single token (the same token, but different per page request) into each anchor's href
attribute in the form of a query string parameter and store a copy of this token in $_SESSION
.
给定要下载的用户特定内容(锚点)的页面,可以href
以查询字符串参数的形式将单个令牌(相同的令牌,但每个页面请求不同)嵌入到每个锚点的属性中,并将该令牌的副本存储在$_SESSION
.
Now, when a logged in user Battempts to use a logged in user A'sshared URL, the whole thing fails because user Aand user Bhave different sessions (or, no session at all), and thus different tokens. In other words, "My link is the same as yours, but different." Anchors would be tied to the session, not just to the page, user, or content.
现在,当登录用户B尝试使用登录用户A 的共享 URL 时,整个事情都会失败,因为用户A和用户B具有不同的会话(或者根本没有会话),因此令牌不同。换句话说,“我的链接和你的一样,但不同。” 锚点将与会话相关联,而不仅仅是与页面、用户或内容相关联。
With that system in place, PHP can determine if a request for content is valid without getting the database involved (by comparing the submitted token to the one in $_SESSION
). What is more, a time limit can be established in $_SESSION
to limit the duration/lifetime of a valid XSRF token. Just use the time()
function and basic math. Sixty minutes might be an ideal token lifetime for an anchor in this situation. Have the user login again if the token for a clicked anchor has expired.
有了该系统,PHP 可以确定对内容的请求是否有效,而无需涉及数据库(通过将提交的令牌与 中的令牌进行比较$_SESSION
)。此外,可以建立时间限制$_SESSION
来限制有效 XSRF 令牌的持续时间/生命周期。只需使用time()
函数和基本数学。在这种情况下,60 分钟可能是锚点的理想令牌生存期。如果单击的锚点的令牌已过期,请让用户再次登录。
Summary
概括
If you use files on a filesystem and store the paths in the database, make sure you do the following (at minimum), too.
如果您使用文件系统上的文件并将路径存储在数据库中,请确保您也执行以下操作(至少)。
- Apply proper file permissions to your content directory (outside of webroot).
- Use random names for uploaded files.
- Check for duplicate file names before saving a file from an upload.
- Only logged in users should be able to download high value content.
- Have an effective
$_SESSION
system that deters session fixation. - Make URLs for high value downloadable content are unique per page by using hashed XSRF tokens.
- XSRF tokens cover more scenarios when they have a terminal life time.
- Make SQL queries for user content based on the logged in user's ID, not the product exclusively.
- Filter and validate all user input.
- Use prepared statements with SQL queries.
- 将适当的文件权限应用于您的内容目录(在 webroot 之外)。
- 对上传的文件使用随机名称。
- 在保存上传的文件之前检查重复的文件名。
- 只有登录用户才能下载高价值内容。
- 有一个有效的
$_SESSION
系统来阻止会话固定。 - 通过使用散列 XSRF 令牌,使高价值可下载内容的 URL 每页都是唯一的。
- XSRF 代币具有终端生命周期时涵盖更多场景。
- 根据登录用户的 ID 而不是产品对用户内容进行 SQL 查询。
- 过滤并验证所有用户输入。
- 将准备好的语句与 SQL 查询结合使用。
回答by Jason
A few options come to mind.
想到了几个选项。
If you are using Apache you can use htaccess to password protect directories. (first googled link : http://www.javascriptkit.com/howto/htaccess3.shtml)
如果您使用的是 Apache,您可以使用 htaccess 来密码保护目录。(第一个谷歌链接:http: //www.javascriptkit.com/howto/htaccess3.shtml)
or Store the files above the web server. Create a script in php that will allow authorised users to access them.
或 将文件存储在 Web 服务器上。在 php 中创建一个脚本,允许授权用户访问它们。
If you want to do it Via FTP, and you are running cpanel you may be able to create new ftp accounts. check yourdomain.com/cpanel to determine if you have it installed.
如果您想通过 FTP 执行此操作,并且您正在运行 cpanel,您可以创建新的 ftp 帐户。检查 yourdomain.com/cpanel 以确定您是否安装了它。
回答by Alex Pliutau
Storing files in DB is very bad practice. Very good practice to store only information about file. Name, extension. Files save on server like $id.$ext. It will be a good architecture. And when user download file, he take file with name in DB.
Sorry for my english.
在 DB 中存储文件是非常糟糕的做法。仅存储有关文件的信息是非常好的做法。名称,扩展名。文件保存在服务器上,如 $id.$ext。这将是一个很好的架构。并且当用户下载文件时,他在数据库中取文件名。
对不起我的英语不好。
回答by Anupam Rekha
Downloadable files can be stored in htaccess protected folder/s. A script like the one below can be used to generate dynamic links for downloadable files.
可下载的文件可以存储在 htaccess 保护的文件夹中。类似下面的脚本可用于生成可下载文件的动态链接。
for ex. Secure download links. http://codecanyon.net/item/secure-download-links/309295
例如。安全下载链接。http://codecanyon.net/item/secure-download-links/309295
回答by odez213
The best way is to store the file reference in Database. The file itself will be stored in the server filesystem. The complexity of this is making sure there is reference integrity between the database file reference and the existing file in the server filesystem. Some database such as sql server 2008 have feature that maintain the integrity of the file references to the actual file itself.
最好的方法是将文件引用存储在数据库中。文件本身将存储在服务器文件系统中。这样做的复杂性在于确保数据库文件引用和服务器文件系统中的现有文件之间存在引用完整性。某些数据库(例如 sql server 2008)具有维护文件引用到实际文件本身的完整性的功能。
Other than that securing the file itself in the server depends on the OS where permissions can be configured to the specific folder where the file reside.
除了在服务器中保护文件本身取决于操作系统,其中可以将权限配置为文件所在的特定文件夹。
回答by Ausmith1
If the files are purely static you could use read-only or WORM media to store the data files or indeed run the complete web server from a "LiveCD". It's certainly not suited to everyone's needs but for limited cases where the integrity of the data is paramount it works.
如果文件是纯静态的,您可以使用只读或 WORM 媒体来存储数据文件,或者确实从“LiveCD”运行完整的 Web 服务器。它当然不适合每个人的需求,但对于数据完整性至关重要的有限情况,它可以工作。