How to hide files link from direct access in PHP (Laravel)

in #codecustoms7 years ago

Now the lot of frameworks are support routing inside, the task is to prevent the user from accessing the file directly, but to convert the path using the function and output the result in browser. The sample writes on Laravel:

In start we should remove confusing url symbols. I use Helpers class to store functions.


public static function base64url_encode($s) {
return str_replace(array('+', '/'), array('-', ''), base64_encode($s));
}
public static function base64url_decode($s) {
return base64_decode(str_replace(array('-', '
'), array('+', '/'), $s));
}

Then we should add the needed encode/decode functions


public static function decryptF($string)
{
$encryption_key = env('ENCRYPT_FILES_KEY'); // it's key from settings, use some string here...
assert(isset($string) === TRUE);
assert(isset($encryption_key) === TRUE);
$result = '';
$string = Helpers::base64url_decode($string);

    for ($i = 0; $i < strlen($string); $i++)
    {
        $char    = substr($string, $i, 1);
        $keychar = substr($encryption_key, ($i % strlen($encryption_key)) - 1, 1);
        $char    = chr(ord($char) - ord($keychar));
        $result .= $char;
    }

    return $result;
}

public static function encryptF($string)
{
    $encryption_key = env('ENCRYPT_FILES_KEY');

    assert(isset($string) === TRUE);
    assert(isset($encryption_key) === TRUE);

    $string = (string) $string;
    $result = '';

    for ($i = 0; $i < strlen($string); $i++)
    {
        $char    = substr($string, $i, 1);
        $keychar = substr($encryption_key, ($i % strlen($encryption_key)) - 1, 1);
        $char    = chr(ord($char) + ord($keychar));
        $result .= $char;
    }

    return Helpers::base64url_encode($result);
}

To catch url's in browser we need write the route below. Files are saving in Laravel storage.

Route::get('/storage/{link}', 'FileController@getFile');

Ok, then, if we want to save the files from form you should write store function in controller, i saving files in 'app/public/poadata'

public function upload($files, $poa_id) // recieve $request->file()
{
foreach ($files as $f) {
$f->move(storage_path('app/public/poadata/poa_'.$poa_id), $f->getClientOriginalName());
}
return redirect('poas.index');
}

To show links for stored files you can use code below. In this case I can store a few files in folder.

$f = Storage::files('/public/poadata/poa_'.$poa->poa_id);
if (isset($f)):
foreach ($f as $file) {
echo '<a href=./storage/'.Helpers::encryptF('/poadata/poa_'.$poa->poa_id.'/'.pathinfo($file)
'filename'].'.'.pathinfo($file)['extension']).' target=_blank>' .pathinfo($file)['filename']. '
';
}
endif

So, the link should be like a http://yoursite/storage/qODmxc_G7dGm1NrG2KKtk93K6d_p2MqXr57nyNE=

To decode this we need to use decryptF function, sample controller part that get file content:

public function getFile($link)
{
try {
$act = Helpers::decryptF($link);
$fullpath = "app/public/" . $act;
return response()->download(storage_path($fullpath), null, [], null);
} catch (FileNotFoundException $e) {
return $e->getCode();
}
}

And finally to block direct links in same folder you need (I use nginx) write sample directive:


location ~* ^/storage/poadata/ {
return 403;
}

That's all ;)

Coin Marketplace

STEEM 0.28
TRX 0.12
JST 0.033
BTC 69942.87
ETH 3793.57
USDT 1.00
SBD 3.73