生成ip和时间限制下载链接

时间:2011-10-27 14:56:32

标签: php download

有一个下载文件的直接链接。用户可以在付款后下载该链接,如下所示:

http://example.com/download/webapp.rar

但我需要生成ip和时间有限的下载链接,以防止leech与他人的文件。我想这样做而不使用任何数据库。像这样的东西:

http://example.com/download.php?a5fds588fgdf

http://example.com/download/a5fds588fgdf

有没有提示?

3 个答案:

答案 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和随机密钥以及到期日期(某些缓存库也可以让您分配缓存有效时间)