Проверка прав на скачивание файла (контролируемое скачивание)

Рейтинг: 0Ответов: 1Опубликовано: 15.04.2015

Задача: нужно проверить права пользователя на доступ к файлу. Например, при просмотре изображения из приватного фотоальбома, как в Вконтакте. Или, как на моём проекте, нужно проверить куплен ли файл, для того, чтобы скачать его.

Предлагаю такую структуру

./
|-- index.php - скрипт для проверки доступа к файлу
`-- secure - директория с приватными файлама
    `-- private.txt - приватный файл

Нужно ограничить доступ к файлам из директории secure по критерию, который будет проверяться в index.php.

При этом файл должен быть доступен для определенных пользователей по адресу, типа :

site.local/files/private.txt

Ответы

▲ 3Принят

Способы решения при использовании php хорошо описаны здесь http://habrahabr.ru/post/151795/. Самый простой способ - использоваь readfile(), однако это довольно накладно в плане ресурсов.

Приведу пример решения с использованием nginx и заголовка X-Accel-Redirect.

Допустим, есть следующая структура

./
|-- index.php - скрипт для проверки доступа к файлу
`-- secure - директория с приватными файлама
    `-- private.txt - приватный файл

Сделаем так, чтобы файл можно было получить по site.local/index.php?path=private.txt, но при этом не был доступен по site.local/secure/private.txt.

Добавим в nginx локейшн

location /secure {
    #директория будет доступна только при внутренних редиректах
    #если получит от бэкэнда заголовок X-Accel-Redirect
    internal;
}

Вот index.php

$secureDir = '/secure/';
//проверяем передано ли имя файла и существует ли файл
//если нет - возвращаем 404 статус
if (
    !isset($_GET["path"]) 
    || empty($_GET["path"]) 
    || !file_exists($file = __DIR__ . $secureDir . $_GET["path"])
){
    header('HTTP/1.0 404 Not Found');
    die('File not found');
}

$path = $_GET["path"]; 

//проверяем права доступа, если нет - 403 статус 
if (!checkAccess($path))
{
    header('HTTP/1.0 403 Forbidden');
    die('403 Forbidden');
}

//заголовок для внутреннего редиректа
header("X-Accel-Redirect: " . $secureDir . $path);
//возвращаем Content-Type, чтобы браузер мог корректно обработать файл
header('Content-Type: ' . mime_content_type($file));


function checkAccess($path)
{
    //реализация проверки прав доступа
    return true;
}

Чтобы сделать ссылки более красивыми, типа site.local/files/private.txt, добавим в конфиг nginx

#преобразует /files/private.txt в /index.php?path=private.txt
location ~* ^/files/(.*) {
    try_files $uri /index.php?path=$1;
}