Ограничиваем доступ к файлам на сервере

Владимир | | CodeIgniter, PHP, Web разработка.

Прежде всего, обратите внимание на то, что все настройки мы храним в отдельном конфигурационном файле application/config/downloader.php.

<?php
$config['filesdir'] = 'archive'; //имя папки с файлами (которые мы разрешаем скачивать)
$config['linktime'] = '120'; //время жизни ссылки на файл (в сек)
?>

Загрузка этого файла выполняется к конструкторе контроллера (строка 14).

Метод index формирует страницу со списком файлов, которые находятся в папке archive. Чтение содержимого папки выполняется с помощью функции get_filenames (входит в File Helper фреймворка), а создание страницы происходит в представлении (application/views/filelist.php).

<?php
//показываем сообщение об ошибке, если оно есть
if ($this->session->flashdata('error')) {
	echo '<h3>'.$this->session->flashdata('error').'</h3>';
}
?>
<h2>Список файлов</h2>
<ol>
<?php
if ($files) {
	foreach ($files as $file) {
		echo '<li>'.anchor('main/confirm/'.$file, $file).'</li>';
	}
}
else {
	echo '<p>Файлы не найдены</p>';
}
?>
</ol>

Как видите, ссылка на каждый из файлов, ведет на страницу main/confirm/file (строка 12), т.е. вызывает метод confirm контроллера и передает в качестве параметра имя файла.

Теперь разберем метод confirm. Он создает страницу с простой математической captcha, которую должен ввести посетитель для того, чтобы скачать файл.

Если captcha введена правильно, то будет создана временная ссылка (об этом чуть ниже) и отправлен редирект на страницу загрузки файла (main/download/link) (строка 50). В противном случае, посетитель останется на этой же странице.

Переходим к методу download. Здесь мы выполняем проверку временной ссылки и отправляем файл посетителю (строки 102 и 105).

Непосредсвенно отправка файла выполняется в методе _sendFile с помощью функции force_download (тоже входит в File Helper).

Если вы внимательно просматривали код, то конечно заметили использование модели mfilelink.

<?php
/**
 * Эта модель предназначена для работы с временными ссылками на файлы
 *
 * @link https://www.simplecoding.org
 * @author Стаценко Владимир <vova_33@gala.net>
 */
class MFileLink extends Model {

	function MFileLink() {
		parent::Model();
	}
	
	/**
	 * Создает временную ссылку и добавляет ее в базу
	 *
	 * @param $fileName - имя файла
	 * @return ссылку, если она создана, false - если возникла ошибка
	 */
	function createLink($fileName) {
		$userIP = $_SERVER['REMOTE_ADDR'];
		$fileLink = md5($userIP.time());
		
		//проверяем существование файла
		if (!get_file_info($this->config->item('filesdir').'/'.$fileName)) {
			return false;
		}

		$qCreateLink = 'INSERT INTO file_downloads (ip, fileLink, expired, fileName)'
			.' VALUES (?, ?, NOW() + INTERVAL '.$this->config->item('linktime').' SECOND, ?)';
		if ($this->db->query($qCreateLink,
			array(
				$userIP,
				$fileLink,
				$fileName
		))) {
			return $fileLink;
		}
		else {
			return false;
		}
	}
	

	/**
	 * Проверяет временную ссылку
	 *
	 * @param $link - временная ссылка на файл
	 * @return имя файла - если ссылка рабочая, false - если нет.
	 */
	function checkFileLink($link) {
		$userIP = $_SERVER['REMOTE_ADDR'];
		
		$qCheckLink = 'SELECT fileName FROM file_downloads WHERE ip=? AND fileLink=? AND (expired >= NOW())';
		$res = $this->db->query($qCheckLink, array($userIP, $link));
		
		if ($res->num_rows() == 1) {
			$r = $res->result_array();
			return $r[0]['fileName'];
		}
		else {
			return false;
		}
	}
}
?>

Как видите, она содержит всего два метода (не считая конструктора).

1) createLink – создает временную ссылку на выбранный файл и сохраняет её в базе данных.

2) checkFileLink – проверяет, можно ли данному посетителю скачивать файл. Для этого, метод ищет подходящую запись в базе данных. Должны совпадать IP, имя ссылки и время завершения её действия должно быть меньше текущего.

Теперь осталось только закрыть доступ к папке archive.

Для этого в корне сайта создаём файл .htaccess со следующим содержимым.

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /path_to_site/

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond $1 !^(index\.php|images|robots\.txt|css)
    RewriteRule ^(.*)$ index.php/$1 [L]
    
    RewriteRule ^(archive.*) index.php/$1 [L]
</IfModule>

<IfModule !mod_rewrite.c>
    ErrorDocument 404 /index.php
</IfModule>

Здесь для нас важно только одно правило (строка 10). С его помощью ко всем запросы, которые начинаются со слова archive добавляется index.php. Таким образом, запрос вроде mysite.com/archive/file.name превращается в mysite.com/index.php/archive/file.name.

В результате запрос будет обработан движком CodeIgniter и посетитель увидит стандартную страницу с 404-ой ошибкой.

Продолжение на следующей странице >>>

Страница: 1 2 3