Безопасные документы с PHP
У меня есть простая система входа / контроля доступа для защиты некоторых запрещенных страниц, но на этих страницах есть ссылки, которые должны быть защищены, например документы Word. Поэтому, если я храню эти ресурсы в корне, они могут быть доступны через URL. Каков наилучший способ обезопасить эти ресурсы, которые находятся на закрытой странице. Я знаю, что могу защитить паролем папку, но пользователю будет предложено дважды, один для запрещенной страницы, а затем для ссылки на ресурс. Любой совет?
2 ответа
У вас есть несколько вариантов здесь, в зависимости от вашего варианта использования.
Используйте PHP для обслуживания файла. По сути, либо перехватывайте все попытки прочитать файл с помощью PHP (используя правило mod_rewrite), либо создайте ссылку непосредственно на PHP и поместите файл (ы) ниже корня документа. Тогда используйте что-то вроде
fpassthru
отправить файл в браузер. Обратите внимание, что вы должны правильно установить заголовки типа содержимого. Также обратите внимание, что это израсходует много ресурсов сервера, так как серверу нужно прочитать весь файл на PHP и отправить его, так что это легко, но не легко.$f = fopen('file.doc', 'r'); if (!$f) { //Tell User Can't Open File! } header('Content-Type: ...'); header('Content-Length: '.filesize('file.doc')); fpassthru($f); die();
Основным преимуществом этого является то, что он прост и переносим (будет работать на всех серверах). Но вы торгуете ценными серверными ресурсами (поскольку пока PHP обслуживает файл, он не может обслуживать другую страницу) для этой выгоды...
Используйте веб-сервер для отправки файла, используя что-то вроде
X-SendFile
(Lighttpd),X-SendFile
(Apache2 / 2.2) илиX-Accel-Redirect
(Nginx). Таким образом, вы будете перенаправлять все запросы к файлу в PHP (вручную или переписать). В PHP вы делаете свою аутентификацию. Вы отправляете заголовки Content-Type, а затем отправляете заголовок какX-SendFile: /foo/file.doc
, Сервер на самом деле отправит файл, так что вам не нужно (это намного эффективнее, чем отправка из PHP изначально).header('Content-Type: ...'); header('X-SendFile: /foo/file.doc'); die();
Основным преимуществом здесь является то, что вам не нужно обслуживать файл из PHP. Вы по-прежнему можете выполнять все свои аутентификацию и регистрацию, которые вам нравятся, но освободите PHP, как только начнете передавать файл.
Используйте что-то вроде
mod_secdownload
(lighttpd) илиmod_auth_token
(Apache). По сути, вы создаете токен в PHP, когда генерируете ссылку на файл. Этот токен представляет собой комбинацию секретного пароля MD5 в сочетании с текущей меткой времени. Преимущество здесь в том, что URL действителен только в течение того времени, которое вы указали в конфигурации (60 секунд по умолчанию). Таким образом, это означает, что ссылка, которую вы даете, будет активна только в течение 60 секунд, а затем любые дальнейшие попытки увидеть содержимое приведут к ошибке серии 400 (я не уверен, что это из головы).$filename = '/file.doc'; $secret = 'your-configured-secret-string'; $time = dechex(time()); $token = md5($secret . $filename . $time); $url = "/downloads/$token/$time$filename"; echo "<a href="$url">Click Here To Download</a>";
Основное преимущество такой работы заключается в том, что с реализацией связано очень мало накладных расходов. Но вам должно быть удобно, чтобы URL действовал только в течение установленного времени (60 секунд по умолчанию)...
Нажмите на CDN для обработки. Это похоже на вариант № 3 (тот, что выше), но использует CDN для обработки файловой службы вместо вашего локального сервера. Некоторые CDN, такие как EdgeCast, предоставляют аналогичную функциональность, когда вы устанавливаете токен, срок действия которого истекает через определенное время. Этот случай будет хорошо работать, если у вас много трафика и вы можете оправдать расходы на CDN. (Примечание: нет связи со связанным CDN, связано только потому, что я знаю, что они предлагают функциональность).
Что касается того, как я лично это сделал, я сделал все вышеперечисленное. Это действительно важно, каков ваш вариант использования. Если вы строите систему, которая будет установлена на общих хостах или нескольких разных серверах, которые вы не контролируете, придерживайтесь первого варианта. Если у вас есть полный контроль и вам необходимо сохранить ресурсы сервера, выполните одно из двух других действий.
Примечание: есть и другие варианты, кроме этих трех. Это просто реализовать, и большинство других параметров достаточно похожи, чтобы соответствовать категории...
Я не пробовал это с текстовыми документами (только с изображениями), но я бы попытался обслужить документ напрямую из php, см. Мой ответ об изображениях.
Это было бы что-то вроде a
тег, ссылающийся на страницу php, которая служит документом Word в качестве типа содержимого.