ruby on Rails 中的文件存储库
我想在 Ruby on Rails 中创建一个简单的文件存储库。用户拥有自己的帐户,登录后可以上传文件或下载以前上传的文件。
这里的问题是安全性。文件应该是安全的,除了所有者之外任何人都不能访问。
- 我应该将文件存储在哪里、哪个文件夹中,以使它们尽可能安全?
- 重命名上传的文件、将名称存储在数据库中并在需要时恢复它们是否有意义?这可能有助于避免名称冲突,但我不确定这是否是一个好主意。
- 文件应该全部存储在一个文件夹中,还是应该稍微分开?
I would like to create a simple file repository in Ruby on Rails. Users have their accounts, and after one logs in they can upload a file or download files previously uploaded.
The issue here is the security. Files should be safe and not available to anyone but the owners.
- Where, in which folder, should I store the files, to make them as safe as possible?
- Does it make sense, to rename the uploaded files, store the names in a database and restore them when needed? This might help avoid name conflicts, though I'm not sure if it's a good idea.
- Should the files be stored all in one folder, or should they be somewhat divided?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是一个有趣的问题。根据您要应用的安全级别,我建议您执行以下操作:
我始终建议将文件重命名为随机生成的哈希值(或增量生成的名称,如 URL 缩短器中使用的名称,请参阅 rubyurl 的开源实现) 。但是,我不会将它们存储在数据库中,因为文件系统是为处理文件而构建的,所以让它完成这项工作。您应该将元数据存储在数据库中,以便在用户下载文件时能够设置正确的文件名。
您应该将文件分区到多个文件夹中。这为您带来了多种优势。首先,文件系统并不是为了处理单个文件夹中的数百万个文件而构建的。如果您的操作尝试从文件夹中获取所有文件,则这会花费更多时间。如果您混淆原始文件名,您可以为文件名中的每个字母创建一个目录,并且每个目录中的文件数量将得到相当好的分布。
最后要考虑的一件事是文件名可能发生冲突。用户不应该能够猜测另一个用户的文件名。因此,您可能需要在这里进行一些额外的检查。
根据您想要实现的安全级别,您可以应用越来越多的模式。
This is an interesting question. Depending on the level of security you want to apply I would recommend the following:
Choose a folder that is only accessible by your app server (if you chose to store in the FS)
I would always recommend to rename the files to a random generated hash (or incremntally generated name like used in URL shorteners, see the open source implementation of rubyurl). However, I wouldn't store them in a database because filesystems are built for handling files, so let it do the job. You should store the meta data in the database to be able to set the right file name when the user downloads the file.
You should partition the files among multiple folders. This gives you multiple advantages. First, filesystems are not built to handle millions of files in a single folder. If you have operations that try to get all files from a folder this takes significantly more time. If you obfuscate the original file name you could create one directory for each letter in the filename and would get a fairly good distributed number of files per directory.
One last thing to consider is the possible collision of file names. A user should not be able to guess a filename from another user. So you might need some additional checks here.
Depending on the level of security you want to achieve you can apply more and more patterns.
只是不要将文件保存在公共文件夹中并创建一个将发送文件的控制器。
从那时起您想要如何组织是您的选择。您可以为每个用户创建一个子文件夹。从安全角度来看,没有必要重命名,但请尝试清理文件名、空格和非 ASCII 字符,这会让事情变得更加困难。
Just don't save the files in the public folder and create a controller that will send the files.
How you want to organise from that point on is your choice. You could make a sub folder per user. There is no need to rename from a security point of view, but do try to cleanup the filename, spaces and non ascii characters make things harder.
对于简单情况(您不想分发文件存储):
将文件存储在
tmp
目录中。不要将它们存储在public
中。然后仅通过进行身份验证/授权检查的路由和控制器公开这些文件。我认为没有任何理由重命名这些文件;您可以根据用户 ID 将它们分成子目录。但是,如果您想允许上传具有相同名称的文件,那么您可能需要为每个文件的名称生成唯一的哈希值或其他内容。
见上文。您可以按照您认为合适的方式对它们进行分区。但我绝对建议对它们进行分区,而不是将它们集中在一个目录中。
For simple cases (where you don't want to distribute the file store):
Store the files in the
tmp
directory. DON'T store them inpublic
. Then only expose these files via a route and controller where you do the authentication/authorisation checks.I don't see any reason to rename the files; you can separate them out into sub directories based on the user ID. But if you want to allow the uploading of files with the same name then you may need to generate a unique hash or something for each file's name.
See above. You can partition them any way you see fit. But I would definitely recommend partitioning them and not lumping them in one directory.