How can I prevent direct access to files using the .htaccess file?

Viewed 100

I have a problem, I tried to restrict access to files with direct link (etc. www.domen.com/folder/subfolder/file.ext), to can only access to them using HTML code like "< img src ='/folder/subfolder/file.ext' >"...

I create .htaccess file with next lines

# enable mod_rewrite
RewriteEngine On
# RewriteCond = define rule condition
# HTTP_REFERER = check from where the request originated
# ! = exclude
# ^ = start of string
# [NC] = case insensitive search
RewriteCond %{HTTP_REFERER} !^http://domen.com/folder/subfolder [NC]
# \ = match any
# . = any character
# () = pattern, group
# $ = end of string
# [F] = forbidden, 403
# [L] = stop processing further rules
RewriteRule \.(gif|jpg|jpeg|png|mp4|mov|mkv|flv)$ - [F,L]

Permission code of my files is 0644 in folders and subfolders, and permission code of my folders and subfolders is 0755

Problem is next.. When I use this code in .htaccess file I restrict direct access to files but at the same time I cant access them with HTML code..

<Directory platform/courses/*>
   Order Allow,Deny
   Allow from 1.1.1.1
   Deny from All
</Directory>
<Directory>
   Order Allow, Deny 
   Allow from All
</Directory>

I tried something like this (with IP addres taken from my cPanel) but I get this result: enter image description here

1 Answers

This is a cutdown version of what I use, so may have syntax errors. The code is laid out to demonstrate the process. It can be made more robust. The user is shown a url with a filename using download.php.
This can be posted.

Once the page is shown, it saves the filename with an expiry of 1 hour in the cookie. If it expires, the page has to be refreshed.

When the button is pressed, sendfile.php gets all the information from the cookie, validates the expiry and filename and sends it.

download.php

This is the landing page that the user can link to.

  1. Show the user a link like /download/document.pdf
  2. Use .htaccess to map it to /download?name=document.pdf
<?php
// Returns the param by name, if not found then get it from the current_url.  
// So this works regardless of how the .htaccess redirection has been done.
function Get_Param ($name, $current_url)
{ $par = filter_var ($_GET [$name] ?? '', FILTER_SANITIZE_STRING);
  if ($par)
     {return $par;}
  if ($only)
     {return '';}
  $pi = pathinfo ($current_url);
  $pi = $pi['filename'] ?? '';
  if (strpos ($pi, '=') == 0)
     {return $pi;}
  else
     {return '';};
}

//Save Information in session with an expiry of 1hr
function Save_Info ($file)
{ $expiry = time()+3610;
  setcookie ('Download',$file, $expiry, '/');
}

//Get the Filename from the param or url
$file = Get_Param ('name', $current_url);
//Save to Session
Save_Info ($file)
// Show page with filename and details
// Show button with link "/sendfile"
?>

sendfile.php

This basically pretends to be the file thats being downloaded and then dies.

<?php
// Sends the file and dies
function Send_File ($file)
{ header ('Content-Description: File Transfer');
  header ('Content-Type: application/octet-stream');
  header ('Content-Disposition: attachment; filename="'.basename($file).'"');
  header ('Expires: 0');
  header ('Cache-Control: must-revalidate');
  header ('Pragma: public');
  header ('Content-Length: ' . filesize($file));
  flush ();
  if (readfile ($file)) {
      //LogIt ($file);
      }
  die ();
}

//Load Info from session and unset it
function Load_Info ()
{ $file = $_COOKIE ['Download'] ?? '';
  unset ($_COOKIE ['Download']);
  return $file
}

//Validate FileName
function Is_Valid ($file,$path)
{ if (!$file) {
     return 'FileName is Blank';
  }
  $file = urldecode($file);
  if (!preg_match('/^[^.][-a-z0-9_.]+[a-z]$/i', $file)) {
     return 'Invalid FileName';
     }
  if (!file_exists($path.$file)) {
     return 'File does not exist';
     }
  return false;
}

//Your actual path to the file
$path ='';
// Load Info from Session
$file = Load_Info ();
// Die if filename invalid or session expired
$error = Is_Valid ($file,$path);
if (!$error) {
    //Show Message and die
   }
else
   {Send_File ($path.$file);
   }
?>
Related