有一个下载文件的直接链接。用户可以在付款后下载该链接,如下所示:
http://example.com/download/webapp.rar
但我需要生成ip和时间限制的下载链接,以防止与他人窃取文件。我想在不使用任何数据库的情况下这样做。像这样:
http://example.com/download.php?a5fds588fgdf
或
http://example.com/download/a5fds588fgdf
有什么提示吗?
这是一个非常好的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的重写,所以你可以自己检查一下。
如果你正在使用以下模块之一,你不需要自己验证所有这些,它在性能方面要好得多,但请注意,它提供了更多的配置,有时还提供了另一种方式来生成url和哈希(参见这里的模块文档)。
或者直接使用nginx安全链接模块:http://wiki.nginx.org/HttpSecureLinkModule
还有一个垂饰:http://redmine.lighttpd.net/wiki/1/Docs:ModSecDownload
或nginx安全下载模块:http://wiki.nginx.org/HttpSecureDownload
也许也有apache的东西…
如果你不担心人们能够解码一些参数,如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);
?>
现在,这是为ip $key->ip获取一个唯一的密钥,有效期为1小时。
验证:
<?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;
会在一行中完成…不过没那么有趣。
我的首要建议是使用数据库!
但是如果你确实必须这样做,那么我建议使用缓存库,如cache-lite: http://pear.php.net/manual/en/package.caching.cache-lite.intro.php
许多PHP框架(如果你正在使用一个)也有一个缓存库
你可以缓存你分配的IP和随机密钥以及一个到期日期(一些缓存库也会让你分配缓存有效时间)