Pull to refresh

Способы разграничения доступов к файлам при помощи php+mysql+apache

Reading time 5 min
Views 3.9K
Задача по разграничению доступа к файлам, которые хранятся на диске довольно редка, но она может возникнуть при написании: online-магазина, который торгует файлами или файлового сервера вроде rapidshare.de. В данной статье я рассмотрю 3-и способа разграничения доступа при помощи php, mysql и специальных модулей веб сервера apache.


Способ #1: использование символьных ссылок

Это самый простой на мой взгляд способ, он не требует установки каких-то дополнительных модулей apache, но в то же время, в чистом виде, это наименее гибкий метод и работать он будет только на сервере под управлением *nix. Темнеменее это метод прекрасно подойдет для файлового хостинга.
Что нужно сделать:
1. Создадим две директории, в одной из которых будут храниться все файлы, доступ к которым нужно ограничить, а вторая пока будет пуста. Для примере я создал у себя директории: members и free;

2. В директории members создадим файл .htaccess с одной директивой «deny from all», таким образом мы закрываем эту директорию и все файлы, которые вней находятся;

3. Для примера создадим в директории members файл test.html. Если обратиться к этому файлу через http то получим Forbidden, т.е. пользователь даже имея прямую ссылку на этот файл не сможет его скачать;

4. Теперь предположим что пользователь авторизовался на вашем сайте или выполнил любые другие действия, после которых он может получить доступ к закрытому файлу. Чтобы дать ему доступ все что нужно это создать символьную ссылку на это файл в директории, которая не закрыта при помощи .htaccess. В моем случае это будет выглядеть примерно так:
exec('cd free; ln -s ../members/test.html test.html');
таким образом в каталоге free у нас будет ссылка на файл из каталога members и мы сможет редиректить на него пользователя или выдать URL.

Так же можно и нужно примешать к названию символьной ссылки какой-нибудь хеш и время, до которого она будет активна. Для удаления просроченных ссылок довольно просто можно написать CLI скрипт и выполнять его по крону раз в N минут.

Способ #2: использование модуля mod_auth_mysql

Этот модуль позволяет реализовать авторизацию пользователя при попытке скачать файл из закрытой .htaccess-ом директории. Поиск пользователя осуществляется в MySQL таблице. Скачать последнюю версию модуля и ознакомиться с документацией можно здесь.
Рассмотрим работу этого модуля на том же примере что и в способе #1, но теперь у нас будет только каталог members.
Что нужно сделать:

1. Скорее всего в базе данных вашего сайта уже есть таблица, в которой хранится список зарегистрированных пользователей сайта, в этом случае вам нужно будет добавить в эту таблицу поле в котором вы будете хранить md5 хеши паролей (если конечно вы их так уже не храните). Но т.к. у меня всего этого нет то я создам таблицу с нуля:
CREATE TABLE users (
id int(11) unsigned not null auto_increment primary key,
login CHAR(50) NOT NULL,
password CHAR(50) NOT NULL,
unique key login_idx (login)
)

Как видно из структуры таблицы поле login должно быть уникальным и не должно содержать значение NULL;

2. В каталоге membert редактируем файл .htaccess и записываем в него следующее:
AuthName "Need authorization" # Заголовок окна авторизации
AuthType Basic # Тип авторизации
AuthMySQLHost <mysql_database_host> # Хост MySQL сервера
AuthMySQLUser <mysql_database_user> # Имя пользователя для доступа к MySQL базе
AuthMySQLPassword <mysql_database_password> # Пароль для доступа к MySQL базе
AuthMySQLDB <mysql_database_name> # Имя MySQL базы
AuthMySQLUserTable users # Имя таблицы, в которой хранятся список пользователей
AuthMySQLNameField login # имя поля в котором храниться логин пользователя
AuthMySQLPasswordField password # имя поля в котором храниться пароль пользователя в виде md5 хеша
AuthMySQLPwEncryption md5 # функция, которой будет взят хеш от пароля
AuthMySQLEnable On # Включаем авторизацию
require valid-user # Требуем валидного пользователя, т.е. нахождения логина и хеша пароля в базе для доступа к файлам каталога


3. Запрашиваем файл из закрытой директории. Это можно сделать двумя способами:
3.1 Просто дав URL на нужный файл, например example.com/members/test.html — в этом случае пользователь увидит диалоговое окно с просьбой ввести логин и пароль. Такой способ не очень удобен, особенно когда речь идет о доступе к большому списку мелких файлов, как например просмотр фото галереи;
3.2 Логин и пароль можно добавить непосредственно в URL файла, например:
test_login:test_password@example.com/members/test.html — в этом случае, если логин и пароль верны, пользователь сразу получит доступ к файлу. Если же совпадения не найдено, то будет выдано диалоговое окно, как в первом варианте. По понятным причинам этот способ выглядит не очень привлекательно из-за соображений безопасности. Эту проблему можно частично решить если в .hataccess заменить строку «AuthMySQLPwEncryption md5» на «AuthMySQLPwEncryption none». В этом случае в URL вместо пароля, нужно добавить его md5 хеш, например: test_login:test_password_hash@example.com/members/test.html

Способ #3: использование модуля mod_auth_cookie_mysql

Этот модуль по своей функциональности очень похож на модуль mod_auth_mysql. Но всеже этот модуль имеет 2-а существенных отличия:
1. Он может брать информацию для авторизации из cookie пользователя;
2. В cookie не фигурирует логин/пароль пользователя, что сводит на нет возможность их кражи.
Скачать модуль и ознакомиться с его документацией можно здесь.

Что нужно сделать:
1. Создадим таблицу в нашей MySQL базе:
CREATE TABLE `users_sessions` (
`cookie_name` varchar(32) NOT NULL,
`cookie_value` varchar(32) NOT NULL,
`expire` int(11) default '0',
`ip` varchar(15) NOT NULL,
`login` varchar(32) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

где: cookie_name — имя cookie, cookie_value — значение cookie, expire — время окончания действия cookie в формате unix timestamp (в php текущее время в этом формате возвращается функцией time()), ip — удаленный IP, с которого зашел пользователь, login — логин текущего пользователя (нужен для создания личных файлов .htaccess).

2. В каталоге members редактируем файл .htaccess заменяя его содержимое на следующее:
# Можно использовать любое слово для определения типа авторизации, например "Cookie"
AuthType Cookie

# Активируем модуль mod_auth_cookie_mysql
AuthCookieSql on

# Обязательные параметры для подключения к базе данных
AuthCookieSql_DBhost <mysql_database_host>
AuthCookieSql_DBuser <mysql_database_user>
AuthCookieSql_DBpassword <mysql_database_password>
AuthCookieSql_DBName <mysql_database_name>

# Имя таблицы, в которой хранятся сессии пользователей. Обязательный параметр
AuthCookieSql_DBtable users_sessions

# Названия полей в таблице. Обязательные
AuthCookieSql_SessnameField cookie_name
AuthCookieSql_SessvalField cookie_value
AuthCookieSql_UsernameField login

# Имя cookie переменной, из которой будет взято значение для поиска в базе.
# Опциональный параметр, если он не указан то поиск совпадений в базе
# будет осуществляться для всех cookie пременных установленных на данный момент
AuthCookieSql_CookieName AuthorizationCookie

# Поле таблицы, в котором хранится время окончания действия cookie.
# Параметр опциональный, если не указан то время действия бесконечно.
AuthCookieSql_ExpiryField expire

# Поле таблицы, в котором хранится удаленный IP пользователя.
# Опциональный параметр, если он не указан то IP не проверяется.
CookieAuth_RemoteIPField ip

# Проверяем найдено ли совпадение в базе
require valid-user


3. После успешной авторизации пользователя на сайте сделаем следующие действия:

// Подготавливаем дату окончания действия cookie
$expire = time() + 60 * 60; // cookie будет действовать 1 час

// Подготавливаем значение для авторизационной cookie
$cookieValue = md5($userPassword . $userLogin . $expire . $_SERVER['REMOTE_ADDR']);

// Устанавливаем авторизационную cookie
setcookie('AuthorizationCookie', $cookieValue);

// Сохраняем значения cookie в базе
mysql_query('insert into users_sessions values ("AuthorizationCookie", "' . $cookieValue . '", ' . $expire . ', "' . $_SERVER['REMOTE_ADDR'] . '", "' . $userLogin . '")');


После этих действий мы можем редиректить пользователя на любой файл, находящийся в каталоге members.

Вот собственно и все. На данный момент это все известные мне способы разграничения прав доступа к файлам под управлением веб сервера apache. Если кто-то знает другие — поделитесь ссылкой и я с удовольствием о них почитаю.
Tags:
Hubs:
+5
Comments 6
Comments Comments 6

Articles