我目前正在为客户创建一个基本上涉及销售各种文件的网站。这显然是一件非常普遍的事情,这让我觉得有点愚蠢,因为我没有想到这样做的方法。
购买完成后,客户应被带到包含下载链接的页面,以及接收包含下载链接的电子邮件和包含将为其创建的帐户信息的电子邮件(他们也将能够从他们的帐户的控制面板下载)。我想弄清楚的是我如何隐藏/隐藏文件在我的服务器上的位置,这样一个购买它的人就不能简单地将直接链接复制并粘贴到其他地方的文件中。即使我下载文件的请求格式为http://example.com/blah/download/454643的链接,这个URL与文件的实际位置不对应,我认为仍然可以在服务器上找到该文件?我真的不太了解权限如何在我的服务器上运行,这就是我问的原因。在此先感谢:)
答案 0 :(得分:8)
您基本上不会向用户提供该文件的直接URL。基于服务器的权限与此无关。
假设您在/data/files/file.pdf中保存了所需的文件(从Web根目录中存储文件的良好做法)。 您可以为用户提供下载链接,其类似于/download.php?auth=32
当用户点击链接时,download.php将检查会话/ cookie是否经过身份验证以及下载ID是否有效(如果您有基于时间的下载过期) 然后download.php将从其位置读取所需文件,并将其发送到具有相应标题的浏览器以强制下载。
答案 1 :(得分:5)
将文件存储在您的Web根目录之外,但是请确保您存储它们的文件夹位于php.ini文件中的“open_basedir”指令中,这将允许您从PHP脚本访问它们。将它们存储在Web根目录之外意味着它们不会通过HTTP直接访问。
有一个PHP脚本,就像这些答案中列出的那些可以流式传输/读出文件的脚本一样。如果它是一个大文件,您可能需要更改“max_execution_time”以考虑脚本读取文件所需的额外时间。此脚本将允许您对用户进行身份验证,并检查他们是否已为该文件付费。
将.htacces放在具有脚本的文件夹中,该脚本将从该文件夹请求的文件重写为变量。这使得它看起来好像是直接访问文件而不是。就个人而言,我只会将单个脚本放在这个文件夹中,只是为了简单起见。所以:
实际上重写为:
祝你好运。http://www.yourdomain.com/files/download_file.php?filename=expensive_song.mp3
答案 2 :(得分:2)
如果您有权运行Lighttpd,那么一定要查看Mod_SecDownload模块。我已经在之前安全销售视频和图像文件的项目中使用过它。
由于网络服务器什么都不知道 关于应用中使用的权限, 生成的URL将可用 每个知道URL的用户。
mod_secdownload删除了此问题 通过介绍一种认证方式 指定时间的URL。该 应用程序必须生成令牌 和一个时间戳,由检查 它之前的网络服务器允许 要下载的文件 网络服务器。
生成的网址必须包含 格式:
< URI前缀> /<令牌GT; /<时间戳式 - 己> /< REL-路径> 看起来像 “yourserver.com/bf32df9cdb54894b22e09d0ed87326fc/435cc8cc/secure.tar.gz”
<令牌GT;是
的MD5
- 秘密字符串(用户提供)
- (以/开头)
- <时间戳式 - 己>
醇>如您所见,令牌未绑定 对用户而言。唯一的限制 factor是使用的时间戳 在给定之后使URL无效 超时(secdownload.timeout)。
答案 3 :(得分:1)
您可以将该网址作为买方的授权码。您让她再次登录,检查代码所针对的文件,然后将文件传送给她。这是osCommerce的PHP代码示例(我很久以前写过)。
// Now send the file with header() magic
header("Expires: Mon, 26 Nov 1962 00:00:00 GMT");
header("Last-Modified: " . gmdate("D,d M Y H:i:s") . " GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
header("Content-Type: Application/octet-stream");
header("Content-disposition: attachment; filename=" . $downloads['orders_products_filename']);
if (DOWNLOAD_BY_REDIRECT == 'true') {
// This will work only on Unix/Linux hosts
tep_unlink_temp_dir(DIR_FS_DOWNLOAD_PUBLIC);
$tempdir = tep_random_name();
umask(0000);
mkdir(DIR_FS_DOWNLOAD_PUBLIC . $tempdir, 0777);
symlink(DIR_FS_DOWNLOAD . $downloads['orders_products_filename'], DIR_FS_DOWNLOAD_PUBLIC . $tempdir . '/' . $downloads['orders_products_filename']);
if (file_exists(DIR_FS_DOWNLOAD_PUBLIC . $tempdir . '/' . $downloads['orders_products_filename'])) {
tep_redirect(tep_href_link(DIR_WS_DOWNLOAD_PUBLIC . $tempdir . '/' . $downloads['orders_products_filename']));
}
}
答案 4 :(得分:1)
以下是我为非常相似的事情所做的示例代码:
// $mimeType is the mime type of the file
header('Content-type: ' . $mimeType);
// this will get the size of the file
// (helps for giving the size to the browser so a percent complete can be shown)
header('Content-length: ' . (string) (filesize($path)));
// disposition is either attachment (for binary files that can't be read by the browser)
// or inline (for files that can be read by the browser
// some times you have play with this to get working so users get the download window in all browsers
// original filename is the name you want to users to see
// (shouldn't have any special characters as you can end up with weird issues)
header('Content-Disposition: ' . $disposition . '; filename=' . $originalFilename);
// the next 2 lines try to help the browser understand that the file can't be cached
// and should be downloaded (not viewed)
header('Pragma: Public');
header('Cache-control: private');
// this will output the file to browser
readfile($path);
您当然可以添加任何登录检查和日志记录,以确保不会下载太多次。
此外,如前所述,请确保将文件放在Web服务器文档根目录的外部(或上方),以便人们无法弄清楚路径。或者您甚至可以在目录上输入密码,这样只有内部人员才能更轻松地访问文件列表,但不建议这样做。 (只有在你可以放置doc根目录之外的东西时才这样做。)
答案 5 :(得分:1)
某些Web服务器(如Lighty和Nginx)实现了X-Sendfile头。假设您有一个Django应用程序,您可以让您的视图返回一个X-Sendfile标题,该标题指向您要发送的文件。然后lighttpd将服务该文件。
该文件可以在非Web访问位置(这不是301重定向),并且因为您的应用程序正在为标题提供服务,您可以先进行授权。
这比从应用程序提供静态文件要好得多。 Web服务器针对静态文件进行了优化,速度更快,资源更轻。如果您处理的是多个请求,则应考虑使用X-Sendfile。
这里有很多关于它的博文:
http://blog.zacharyvoase.com/2009/09/08/sendfile/
Lighttpd / PHP说明可以在这里找到:
http://redmine.lighttpd.net/wiki/1/X-LIGHTTPD-send-file
NGINX说明可以在这里找到:
http://wiki.nginx.org/XSendfile
似乎早期发布的Apache mod也做同样的事情:
答案 6 :(得分:0)
我看到很多基于购买的下载网址倾向于使用一些guid和其他动态信息作为网址的一部分,而不是像猜测一个id一样简单。你最终可能会使用guid / datetimepurchased / id或类似的东西作为路径的一部分。
另一个选择是确保用户在允许下载进行之前登录,这将提供额外的安全层。
答案 7 :(得分:0)
嗯,首先,您绝对不想直接链接到该文件。如果满足某些条件,您可能希望向用户发送一个链接到您创建的服务(甚至只是一个页面),其中包含生成的id参数,导致文件下载。
这些标准很难,实际上,因为您需要允许用户多次下载文件(如果他第一次没有下载完整的文件,或者意外删除它等等),但是链接有效,直到你杀了它。
我建议使用时间或IP来过滤下载请求。
时间:当有人从您那里购买文件时,请告知他们他们只能下载文件1天,或者其他一些文件。是的,其他人可以在当天下载文件,但仅限1天。您还可以对此设置下载限制,因此他们只能下载5次(这是正常的)。
IP:当有人从您那里购买文件时,告知他们他们只能从该IP下载文件。您的下载服务当然可以在尝试下载文件时进行检查。
似乎两者同时也很容易使用。
在任何一种情况下(或两者兼而有之),准备好处理未及时下载文件的客户,或者希望在时间限制之后再次获取文件(或者从另一台计算机/ IP(有些人没有获得)静态的))。他们不想再付钱,也许不应该付钱。