2011-10-27 36 views
5

有一個直接鏈接下載文件。用戶可以下載該鏈接付款後,像這樣:生成ip和時間限制下載鏈接

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

但我需要生成IP和時間限制的下載鏈接,以防止水蛭與他人的文件。我想在不使用任何數據庫的情況下這樣做。是這樣的:

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

http://example.com/download/a5fds588fgdf 

有什麼祕訣嗎?

+10

「沒有任何數據庫」?這是一個什麼樣的要求?你*絕對*必須存儲一些數據來解決這個問題,並且數據庫是迄今爲止最好的地方*這樣做。你爲什麼試圖避免使用數據庫? – meagar

+0

如果沒有數據庫,可以通過設置'expiry'來使用'cookies'來實現。然而,麻煩的是你可以刪除cookie。所以這不是可靠的方法。 –

+1

@GhazanfarMir ...除了這樣的事實,即餅乾可以很容易欺騙,以至於使它們幾乎沒用這個... – DaveRandom

回答

23

有一個非常好的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'); 
} 

現在你只需要到下載改寫這個「中間人」 -script和你做。

例改寫爲nginx的:

location /download { 
    rewrite ^.*$ /download.php last; 
    break; 
} 

我真的不familar與Apache重寫,所以你可以檢查這個自己。

如果您使用以下模塊中的一個,你不需要親自驗證,這是更好的性能明智的,但請注意,它可以提供更多的配置,有時另一種方式來生成URL和散列(見模塊docs here)。

,或者你只是使用nginx的安全鏈接模塊:http://wiki.nginx.org/HttpSecureLinkModule

還爲萊蒂掛件:http://redmine.lighttpd.net/wiki/1/Docs:ModSecDownload

或者nginx的安全下載模塊:http://wiki.nginx.org/HttpSecureDownload

也許有一些是阿帕奇太...也許你可以做一些改寫那裏...

+0

這是一個了不起的方式把它!謝謝 ! – Tom

+0

@ Hikaru-Shindo謝謝你的伴侶,你可以把我的樣本鏈接到你的腳本(爲我的測試) – Nulled

+0

@NuLLeR我已經重寫了我的答案,以符合你的例子,並增加了一些更多的信息。 –

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 $鍵 - > 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

@meagar問題? – Tom

+0

比k你讓我在工作中LOL。 – meagar

+0

@Tom謝謝,我必須在其中設置我的文件名「webapp.rar」? – Nulled

0

我的第一條建議是使用數據庫!

但是,如果你絕對肯定要做它沒有,那麼我會建議使用一個緩存庫像緩存精簡版:http://pear.php.net/manual/en/package.caching.cache-lite.intro.php

許多PHP框架(如果您正在使用一個)還配備了一個緩存庫

您可以緩存你有到期日指定沿着IP和隨機密鑰(一些緩存庫還可以讓你指定緩存有效時間)