Назад | Перейти на главную страницу

Как я могу защитить файлы на моем сервере NGiNX?

Я пытаюсь защитить файлы на своем сервере (несколько типов) с помощью NGiNX и PHP.

В основном я хочу, чтобы люди входили на сайт, если они хотят получить доступ к этим статическим файлам, таким как изображения. DropBox делает это очень хорошо. Где они заставляют вас войти в систему, чтобы получить доступ к любым статическим файлам, которые вы размещаете на сервере.

Я думал об использовании модуля NGiNX Perl. И я бы написал сценарий perl, который проверял бы сеанс, чтобы узнать, вошел ли пользователь в систему, чтобы предоставить ему доступ к статическому файлу.

Я бы предпочел использовать PHP, потому что весь мой код работает под PHP, и я не уверен, как проверить сеанс, созданный PHP, с помощью PERL.

Итак, в основном мой вопрос: как я могу защитить статические файлы любых типов, которые потребуют от пользователя входа в систему и создания действительного сеанса с помощью сценария PHP?

Вы спрашиваете о двух вещах:

  1. Как предотвратить внешний доступ к (набору) файлов
  2. Как аутентифицировать пользователя и разрешить PHP (и пользователю) доступ к файлу (ам)

Надеюсь, это проясняет роль, которую играет каждый компонент, хотя она может быть немного чрезмерной.

Запретить внешний доступ к файлам:

Эта часть выполняется вашим веб-сервером - в данном случае nginx.

В вашей конфигурации nginx (ваш серверный блок) вы указываете root дорожка. По умолчанию все файлы по этому корневому пути доступны напрямую.

Например, рассмотрим следующее (домен - example.com)

root /var/www/example.com/public_html

Если у вас есть файл, uploaded_file.zip, он будет доступен следующими способами:

  • Расположение: /var/www/example.com/public_html/uploaded_file.zip - доступный через example.com/uploaded_file.zip
  • Расположение: /var/www/example.com/uploaded_file.zip - не доступный (даже используя example.com/../uploaded_file.zip)

По сути, файл над корнем документа не будет доступен через браузер, однако большинство конфигураций PHP позволяют вашему коду читать файл и доставлять его (ограничения на это часто являются результатом open_basedir)

В некоторых сценариях может быть предпочтительнее размещать файлы в корне документа. Чтобы сделать это и при этом предотвратить (прямой) внешний доступ, вы будете использовать internal директива. Например:

расположение / загрузки {внутренние; }

Теперь любые файлы, размещенные в /var/www/example.com/public_html/uploads, доступны только изнутри (т.е. не могут быть доступны через браузер, но могут быть доступны через ваши сценарии PHP). При желании вы также можете настроить псевдоним для местоположения / uploads, чтобы можно было использовать другой путь для ссылки на него.

На данный момент ваши файлы недоступны напрямую, но ваши скрипты все еще могут их обслуживать.

Аутентификация пользователя и PHP:

Рассмотрим следующий базовый дизайн: пользователь может получить доступ к файлу напрямую или перейти на страницу входа. Если они попытаются получить доступ к файлу напрямую и вошли в систему (и имеют разрешение), файл загрузится, в противном случае они окажутся на экране входа в систему. Чтобы загрузить файл, пользователь должен войти в систему.

Допустим, ваш сценарий загрузки (страница, которая доставит файл пользователю) называется «download.php». Типичный URL-адрес может быть example.com/download.php?file=uploaded_file.zip. Вполне вероятно, что вы не хотите, чтобы ваши URL-адреса включали имя файла php. Чтобы этого избежать, вы можете настроить правило перезаписи в своей конфигурации nginx, которое будет указывать другое место (скажем, / files) в вашем скрипте. Добавьте в конфигурацию nginx:

rewrite ^/files/(.*) /download.php?file=$1 last;

(Это означает изменение запрошенного пути любых запросов, начинающихся с / files, и захват всего, что находится после /, и передачу его в качестве параметра запроса в ваш файл php);

Теперь к вашему файлу можно получить доступ через: example.com/files/uploaded_file.zip (который внутренне перенаправляет на ваш php-скрипт).

Ваш PHP-файл (download.php) теперь выполняет следующие функции:

  • Начать сеанс
  • Если пользователь вошел в систему, продолжайте, в противном случае перенаправьте на страницу входа, передав целевой файл как часть строки запроса.
  • Запросите свою базу данных (например, MySQL), чтобы узнать, может ли пользователь получить доступ к этому файлу.
    • Если у пользователя есть разрешение, продолжайте, в противном случае перенаправьте на страницу с ошибкой
  • Выведите необходимые заголовки (Content-Type, Content-Disposition и т. Д.) И установите:

    X-Accel-Redirect: /uploads/uploaded_file.zip;

Обратите внимание: вы можете выполнить фактическую загрузку полностью с PHP (например, используя readfile) - просто немного эффективнее, особенно для больших файлов) делать это через nginx. Кроме того, несмотря на то, что пользователь, похоже, обращается к файлу напрямую, внутри он проходит через PHP, который аутентифицирует их, прежде чем разрешить им продолжить.

URL -> nginx (redirect to PHP) -> PHP (authenticate) -> nginx (serve file)

Что касается загрузки, вы будете move_uploaded_file в /var/www/example.com/public_html/uploads (который защищен «внутренней» директивой, поэтому к файлам нельзя получить прямой доступ) и сохраните разрешения в своей базе данных.