Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate ip and time limited download link

Tags:

php

download

there is a direct link for download a file. users can download that link after payout, like this:

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

But I need generate ip and time limited download link to prevent leech the file with others. I want to do this without use any databases. something like this :

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

or

http://example.com/download/a5fds588fgdf

is there any tips?

like image 290
Morteza Avatar asked Oct 27 '11 14:10

Morteza


2 Answers

There is a really good nginx module doing this.

The URL gets two parameters - Let's call them s (security) and t (timestamp). Security is a secure hash generated from timestamp, path and a salt (in your case just add the 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

To verify:

$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');
}

Now you just need to rewrite the downloads to this "man in the middle"-script and you are done.

Example rewrite for nginx:

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

I'm not really familar with apache rewrites so you may check for this yourself.

If you are using one of the following modules you do not need to verify all this yourself and it is much better performance-wise but note that it affords more configuration and sometimes another way to generate the url and hash (see module docs here).

Or you just use the nginx secure link module: http://wiki.nginx.org/HttpSecureLinkModule

There is also a pendant for lighty: http://redmine.lighttpd.net/wiki/1/Docs:ModSecDownload

Or the nginx secure download module: http://wiki.nginx.org/HttpSecureDownload

Maybe there is something for apache too... Maybe you could do something with rewrites there...

like image 100
Hikaru-Shindo Avatar answered Sep 30 '22 05:09

Hikaru-Shindo


If you are not concerned about people being able to decoding some parameters such as IP or timestamp you could try something like this :

<?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);
?>

Now that's for getting a unique key, valid 1 hour, for ip $key->ip.

To verify it :

<?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 ?');
}
?>

And you're done :) No database involved. Just hashing and matching hashes afterwards.

But I guess a simple $_SESSION[$file_id] = time()+3600; would do the trick in one line...Not as fun though.

like image 42
Tom Avatar answered Sep 30 '22 05:09

Tom