简体   繁体   English

禁止在直接http上访问文件

[英]Prevent file access on direct http

My question seems to be similar to others here in SO, I have try a few but it doesn't seem to work in my case... 我的问题似乎与此处的其他问题类似,我尝试了一些,但似乎不适用于我的情况...
I have develop a site in which you have to fill up a form and then it returns a PDF file that you can download or print, this file is saved so you can retrieve it later 我已经开发了一个站点,您必须在其中填写表格,然后返回一个PDF文件,您可以下载或打印该文件,此文件已保存,以便以后检索

public_html
      |_index.php
      |_<files>
      |    |_file_001.pdf
      |    |_file_002.pdf
      |_<asstes> ....etc

that is how my files and folders look on the server, anyone can easily guess other files, .com/folder/file_00X.pdf , where X can be change for any other number and get access to the file... the user after finish with the form the script returns a url .com/file/file_001.pdf so he/she can click on it to download... 这就是我的文件和文件夹在服务器上的显示方式,任何人都可以轻松猜出其他文件.com/folder/file_00X.pdf ,其中X可以更改为任何其他数字并可以访问该文件...完成后用户脚本的形式返回一个URL .com/file/file_001.pdf因此他/她可以单击它进行下载...
a year ago I did something similar an script to generate PDF's but in that case the user needed the email and a code that was sent via email in order to generate the PDF and the PDF's are generated on demand not saved like in this case... 一年前,我做了类似的脚本来生成PDF,但是在那种情况下,用户需要电子邮件和通过电子邮件发送的代码才能生成PDF,而PDF却按需生成,但这种情况下并没有保存。 。
Is there a way to protect this files as they are right now? 有没有办法保护当前的文件?
or, do I have to make it a little bit more hard to guess? 或者,我是否必须增加猜测的难度?
something like. 就像是。
.com/files/HASH(MD5)(MICROTIME)/file_(MICROTIME)_001.pdf
and save the file and folder name in the DB for easy access via admin panel, the user will have to get the full URL via email... 并将文件和文件夹名称保存在数据库中以便通过管理面板轻松访问,用户将必须通过电子邮件获取完整的网址...

Any ideas would be greatly appreciated. 任何想法将不胜感激。

For full security i would move the PDFs out of the public folder and have ascript in charge of delivering the content. 为了全面安全起见,我会将PDF从公共文件夹中移出,并由脚本负责传递内容。 If the form is filled correctly, you can generate a temporary hash and store that hash and the pdf path in the database. 如果正确填写了表格,则可以生成一个临时哈希并将该哈希和pdf路径存储在数据库中。 That way the user will have access to the file as a link through the retriever script, but you will control for how long he will have that link available. 这样,用户将可以通过检索器脚本以链接的形式访问文件,但是您将控制他可以使用该链接多长时间。

Imagine the temporary link being http://yourdomain/get_pdf/THIS_IS_THE_HASH 想象一下临时链接是http:// yourdomain / get_pdf / THIS_IS_THE_HASH

  • Move the PDF's to some non-public folder (that your web server has access to but the public does not). 将PDF移到某些非公共文件夹(您的Web服务器可以访问,但公共文件夹不可以)。 Or you can use .htaccess to restrict access to the pdf's in their current location. 或者,您可以使用.htaccess限制对pdf当前位置的访问。

  • Write a php script that returns the correct pdf based on some passed in http variable. 编写一个php脚本,该脚本根据传入的http变量返回正确的pdf。

You can secure/restrict this any way that you want to. 您可以根据需要以任何方式保护/限制这种情况。
For example, one answer suggested using a temporary hash. 例如,一个答案建议使用临时哈希。

Other options for restricting access: 其他限制访问的选项:

  • Store in the user's session that they submit the form and have a download pending, that way no one could direct link. 在用户会话中存储他们提交的表单并等待下载,这样没人可以直接链接。
  • Check the referrer header. 检查引荐来源标头。 If it is a direct request then do not serve the file. 如果是直接请求,则不要提供文件。

Here is a code example using the last option: 这是使用最后一个选项的代码示例:

$hash_or_other_identifier = $_REQUEST["SomeVariable"];

if (!$_SERVER["HTTP_REFERER"])
{
    //dont serve the file
} else {
    //lookup the file path using the $hash_or_other_identifier
    $pdfFile = somelogic($hash_or_other_identifier);

    //serve the correct pdf
    die(file_get_contents($pdfFile));
}

I don't even think that keeping the file name secret is a very big deal if all you are worried about is people typing it into the URL bar because you can simply check if it is a direct link or not. 我什至不认为如果您担心的是仅是人们在URL栏中键入文件名,对文件名保密就没有什么大不了的,因为您可以简单地检查它是否是直接链接。 If you are also worried about bots or clever people who will create a link that points to your file so it looks like a referrer, then you will need to add stricter checks. 如果您还担心机器人程序或聪明的人会创建指向您文件的链接,使它看起来像是引荐来源,那么您将需要添加更严格的检查。 For example, you can verify that the referrer is your own site. 例如,您可以验证引荐来源网址是您自己的网站。 Of course headers can be spoofed so it all just depends how bulletproof it needs to be. 当然标题可以被欺骗,所以这完全取决于它需要的防弹性能。

The url would be something like: http://yourdomain/pdf?SomeVariable=12345 该网址将类似于: http://yourdomain/pdf?SomeVariable=12345

However, you don't have to use an http variable. 但是,您不必使用http变量。 You can also use a url fragment with the same result, eg: http://yourdomain/pdf/12345 您还可以使用具有相同结果的url片段,例如: http://yourdomain/pdf/12345

General guidelines: 一般准则:

  • File is not in the directory that's accessible via HTTP 文件不在可通过HTTP访问的目录中
  • Use a database or any other storage to link up file location with an identifier (an auto incremented number, guid, hash, whatever you deem fit). 使用数据库或任何其他存储设备来将文件位置与标识符(自动递增的数字,guid,哈希,以及您认为合适的任何标识符)链接起来。 The location of the file could be in the server's file system or on a shared network location etc. 文件的位置可以在服务器的文件系统中,也可以在共享的网络位置等上。
  • Instead of hashes, it's also practical to encrypt the ID generated by the database, base64 encode it and provide it back - that makes it nearly impossible to guess the valid string that one needs to send back in order to refer to a file 除了散列之外,还可以对数据库生成的ID进行加密,对base64进行编码并提供回去,这实际上是可行的,这使得几乎不可能猜出为了引用文件而需要回送的有效字符串。
  • Use a PHP script that delivers the file if user authentication passes (in case you need authenticated users to be able to retrieve the file) 如果用户身份验证通过(请使用经过身份验证的用户才能检索文件),则使用PHP脚本来传递文件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM