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


Generate ip and time limited download link

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

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和随机密钥以及一个到期日期(一些缓存库也会让你分配缓存有效时间)