有一个下载文件的直接链接。用户可以在付款后下载该链接,如下所示:
http://example.com/download/webapp.rar
但我需要生成ip和时间有限的下载链接,以防止leech与他人的文件。我想这样做而不使用任何数据库。像这样的东西:
http://example.com/download.php?a5fds588fgdf
或
http://example.com/download/a5fds588fgdf
有没有提示?
答案 0 :(得分:26)
有一个非常好的nginx模块可以做到这一点。
URL有两个参数 - 让我们称之为s(安全性)和t(时间戳)。安全性是从时间戳,路径和盐生成的安全哈希(在您的情况下只是添加IP)。
$ip = $_SERVER['REMOTE_ADDR'];
$salt = 'change me cause im not secure';
$path = '/download/webapp.rar';
$timestamp = time() + 3600; // one hour valid
$hash = md5($salt . $ip . $timestamp . $path); // order isn't important at all... just do the same when verifying
$url = "http://mysite.com{$path}?s={$hash}&t={$timestamp}"; // use this as DL url
验证:
$ip = $_SERVER['REMOTE_ADDR'];
$salt = 'change me cause im not secure';
$path = $_SERVER['REQUEST_URI'];
$hashGiven = $_GET['s'];
$timestamp = $_GET['t'];
$hash = md5($salt . $ip . $timestamp . $path);
if($hashGiven == $hash && $timestamp <= time()) {
// serve file
} else {
die('link expired or invalid');
}
现在你只需要将下载重写为这个“中间人” - 脚本,你就完成了。
nginx的重写示例:
location /download {
rewrite ^.*$ /download.php last;
break;
}
我并不熟悉apache重写,所以你可以自己检查一下。
如果您使用以下模块之一,则无需自行验证所有这些模块,并且性能要好得多,但请注意,它提供了更多配置,有时还提供了生成网址和哈希的其他方法(请参阅模块文档)这里)。
或者您只需使用nginx安全链接模块:http://wiki.nginx.org/HttpSecureLinkModule
还有一个轻盈的坠饰:http://redmine.lighttpd.net/wiki/1/Docs:ModSecDownload
或者nginx安全下载模块:http://wiki.nginx.org/HttpSecureDownload
也许还有apache的东西......也许你可以用重写来做点什么......
答案 1 :(得分:4)
如果您不担心人们能够解码某些参数(如IP或时间戳),您可以尝试这样的事情:
<?php
$salt = 'SALTING'; // Hash cipher
$key = new stdClass();
$key->limit = time()+3600; // 1 hour limit
$key->ip = $_SERVER['REMOTE_ADDR'];
$key->security = sha1(sha1($salt.serialize($key))); // Double sha1 for fun
$key_param = base64_encode(serialize($key));
echo sprintf('http://mysite.com/download/%s', $key_param);
?>
现在是获取一个唯一密钥,有效1小时,用于ip $ key-&gt; ip。
验证它:
<?php
$salt = 'SALTING';
$key = $_GET['key'];
$key = base64_decode($key);
$key = unserialize($key);
if($key->security != sha1(sha1($salt.serialize($key)) || $_SERVER['REMOTE_ADDR'] != $key->ip) {
throw new Exception('Security breach. U mad bro ?');
}
?>
你已经完成了:)没有涉及数据库。之后只是哈希和匹配哈希。
但我想一个简单的$_SESSION[$file_id] = time()+3600;
会在一行中完成这个诀窍......虽然不是很有趣。
答案 2 :(得分:0)
我最重要的建议是使用数据库!
但如果你绝对肯定必须这样做,我会建议你使用像cache-lite这样的缓存库:http://pear.php.net/manual/en/package.caching.cache-lite.intro.php
许多PHP框架(如果您使用的话)也附带了一个缓存库
您可以缓存分配的IP和随机密钥以及到期日期(某些缓存库也可以让您分配缓存有效时间)