Подтвердить что ты не робот

Использование PHP/Apache для ограничения доступа к статическим файлам (html, css, img и т.д.)

Допустим, у вас много файлов html, css, js, img и etc в каталоге на вашем сервере. Обычно любой пользователь интернет-земли может получить доступ к этим файлам, просто набрав полный URL-адрес, например: http://example.com/static-files/sub/index.html

Теперь, если вы хотите, чтобы только авторизованные пользователи могли загружать эти файлы? В этом примере, скажем, ваши пользователи сначала регистрируются в URL-адресе: http://example.com/login.php

Как бы вы разрешили зарегистрированному пользователю просматривать файл index.html(или любой из файлов под "статическими файлами" ), но ограничивать файл для всех остальных?

На сегодняшний день у меня появилось два возможных решения:

Решение 1
Создайте следующий файл .htaccess в разделе "static-files":

Options +FollowSymLinks  
RewriteEngine on  
RewriteRule ^(.*)$ ../authorize.php?file=$1 [NC]

И затем в authorize.php...

if (isLoggedInUser()) readfile('static-files/'.$_REQUEST['file']);
else echo 'denied';

Этот файл authorize.php сильно упрощен, но вы получаете идею.

Решение 2
Создайте следующий файл .htaccess в разделе "static-files":

Order Deny,Allow
Deny from all
Allow from 000.000.000.000

И тогда моя страница входа в систему могла бы добавить этот файл .htaccess с IP для каждого пользователя, входящего в систему. Очевидно, для этого также потребуется какая-то процедура очистки, чтобы очистить старые или более не используемые IP-адреса.


Я беспокоюсь, что мое первое решение может стать довольно дорогостоящим на сервере, так как увеличивается количество пользователей и файлов, к которым они обращаются. Я думаю, что мое второе решение будет намного дешевле, но также менее безопасно из-за IP-спуфинга и т.д. Я также опасаюсь, что запись этих IP-адресов в файл htaccess может стать узким местом приложения, если есть много одновременных пользователей.

Какое из этих решений звучит лучше и почему? Или вы можете подумать о совершенно другом решении, которое было бы лучше, чем любое из этих?

4b9b3361

Ответ 1

Я хотел бы использовать загрузчик PHP для проверки подлинности, а затем вернуть нужные вам файлы. Например, вместо выполнения <img src='picture.jpg' /> Сделайте что-то вроде <img src='load_image.php?image=picture.jpg' />.

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

Не забудьте вернуть правильные заголовки в PHP и сделать что-то вроде readfile() в php и вернуть содержимое файла в браузер.

Я использовал эту настройку на нескольких веб-сайтах с большим размером и работает как прелесть.

Изменить: система, которую я сейчас создаю, использует этот метод для загрузки Javascript, изображений и видео, но CSS мы не очень беспокоимся о безопасности.

Ответ 2

X-Sendfile

Там есть модуль для Apache (и других HTTP-серверов), который позволяет вам сообщить HTTP-серверу, чтобы он служил файлу, указанному в заголовке в вашем php-коде: Итак, ваш php script должен выглядеть так:

// 1) Check access rights code
// 2) If OK, tell Apache to serve the file
header("X-Sendfile: $filename");

2 возможных проблемы:

  • Вам нужен доступ для перезаписи правил (.htaccess включен или прямой доступ к файлам конфигурации)
  • Вам нужен модуль mod_xsendfile, добавленный в установленный Apache

Вот хороший ответ в другом потоке: fooobar.com/questions/65289/...

Ответ 3

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

Но у меня просто была очень интересная идея, которая могла бы работать.

  • Поддерживайте каталог с именем /sessions где-то на вашем веб-сервере.

  • Всякий раз, когда пользователь входит в систему, создайте пустой текстовый файл с идентификатором сеанса в /sessions. Например. 123456

  • В вашем приложении PHP выполните следующие образы: /sessions/123456/images/test.jpg

  • В вашем файле htaccess есть две команды перенаправления.

  • Тот, который переводит /sessions/123456/images/test.jpg в /sessions/123456?filename=images/test.jpg

  • Вторая, которая ловит любые вызовы //sessions/(.*) и проверяет, существует ли указанный файл, используя флаг -f. Если /sessions/123456 не существует, это означает, что пользователь вышел из системы или истек срок их сеанса. В этом случае Apache отправляет 403 или перенаправляет страницу ошибки - ресурс больше не доступен.

Таким образом, у нас есть квазисеансная аутентификация в mod_rewrite, выполняющая только один "файл существует"!!

У меня нет достаточной рутины для создания операторов mod_rewrite на лету, но они должны быть достаточно легкими для записи. (Я надеюсь с вашей стороны @Gumbo:)

Примечания и оговорки:

  • Истекшие файлы сеансов должны быть быстро удалены с помощью задания cron, если только не возможно проверить файл mtime в .htaccess(что вполне возможно).

  • Изображение/ресурс доступен любому клиенту, пока существует сессия, поэтому нет 100% защиты. Возможно, вы можете обойти это, добавив IP-адрес клиента в уравнение (= имя файла, которое вы создаете), и выполните дополнительную проверку для% {REMOTE_ADDR}. Это продвинутое .htaccess мастерство, но я уверен, что это выполнимо.

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

Мне очень интересны отзывы об этом, любые недостатки или невозможности, которые я, возможно, упустил, и любые успешные реализации (у меня нет времени на то, чтобы настроить сам тест).

Ответ 4

Создайте переписать карту, которая проверяет учетные данные пользователя и перенаправляет их на соответствующий ресурс или на страницу "отказано в доступе".

Ответ 5

Сохранение содержимого файлов htaccess выглядит кошмаром. Кроме того, ваша заявленная цель заключается в том, чтобы не разрешать пользователям, не прошедшим аутентификацию, не не аутентифицированным клиентским IP-адресам, доступ к этому контенту, поэтому подход не подходит для цели:

Несколько пользователей могут отображаться с одного и того же IP-адреса

Кажется, что сеанс одиночных пользователей поступает из нескольких адресов.

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

Если вы хотите, чтобы ваш контент не выходил, и вы не хотите использовать аутентификацию HTTP, то единственный доступный для доступа к нему доступ к файлам в дополнительном слое логики - единственный разумный выбор. Кроме того, вы не знаете, что с помощью PHP для этой есть проблема - вы ее протестировали? Я думаю, вы будете удивлены, сколько пропускной способности он может обеспечить, особенно если вы используете кеш-код операции.

Я предполагаю ваше "упрощение" проблем с обертками, таких как тип mime и кеширование.

С.

Ответ 6

Я написал динамическое веб-приложение и развернул его на WebShere Application Server, и вот как я защитил свои статические файлы:

Сначала я добавил

<login-config id="LoginConfig_1">
  <auth-method>FORM</auth-method>
    <realm-name>Form-Based Authentication</realm-name>
      <form-login-config>
        <form-login-page>/login.html</form-login-page>
        <form-error-page>/login_error.html</form-error-page>
       </form-login-config>
</login-config>

в web.xml, который скажет вашему веб-серверу использовать проверку подлинности на основе форм (код для использования логина приведен ниже).

код для страницы входа:

<form id="form1" name="form1" method="post" action="j_security_check" style="padding: 0px 0px 0px 12px;">
        Username: 
          <label>
          <input name="j_username" type="text" class="font2" />
        </label>

        <br />
        <br />
        Password:
        <span class="font2" >
        <label>
      <input name="j_password" type="password" class="font2" />
      </label>
      </span> 
        <br />
        <br />
            <label>
        <input type="submit"  class="isc-login-button" name="Login" value="Login" />
        </label>
    </form></td>

Чтобы сделать регистрацию на основе форм, вы должны настроить свой веб-сервер для использования определенной пользовательской регистрации, которая может быть LDAP или базой данных.

Вы можете объявить свои защищенные ресурсы и всякий раз, когда пользователь пытается получить доступ к такому ресурсу, контейнер автоматически проверяет, прошел ли аутентификация пользователя или нет. Даже вы можете прикреплять роли также к защищенным ресурсам. Для этого я добавил следующий код в свой web.xml

<security-constraint>
        <display-name>Authenticated</display-name>
        <web-resource-collection>
            <web-resource-name>/*</web-resource-name>
            <url-pattern>/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>PUT</http-method>
            <http-method>HEAD</http-method>
            <http-method>TRACE</http-method>
            <http-method>POST</http-method>
            <http-method>DELETE</http-method>
            <http-method>OPTIONS</http-method>
        </web-resource-collection>
        <auth-constraint>
            <description>Auth Roles</description>
            <role-name>role1</role-name>            
            <role-name>role2</role-name>            
        </auth-constraint>
    </security-constraint>

    <security-role>
        <role-name>role1</role-name>
    </security-role>
    <security-role>
        <role-name>role2</role-name>
    </security-role>

Таким образом, этот код не позволит пользователю увидеть какой-либо статический файл (с/*), пока он не войдет в систему под роль role1 и role2. Таким образом, вы можете защитить свои ресурсы.

Ответ 7

Если вы используете apache, вы можете настроить, как показано ниже, в файле .htaccess или httpd.conf. Ниже приведен пример предотвращения доступа к *.inc файлу. Это очень помогает мне.

<Files ~ "\.inc$">
Order allow,deny
Deny from all
</Files>

Подробнее см.: http://www.ducea.com/2006/07/21/apache-tips-tricks-deny-access-to-certain-file-types/.

Ответ 8

Предположим, что вы хотите защитить все свои статические файлы, и вам нужно их от сервера внутри вашего веб-сайта, вы можете защитить все HTTP-методы, кроме HEAD. Если вы авторизованы, вы делаете запрос заголовка через заголовки и отправляете filecontent как тело. Конечно, это дорого, но вы защищены и у вас такое же поведение.

Ответ 9

У меня может быть предложение, основанное на iframe и HTTP_REFERER, но это не доказательство пули, и это будет зависеть от того, что именно вы хотите защитить с помощью этого доступа.

Но в случае предотвращения полной статической страницы, которая будет отображаться без проверки подлинности, вы можете сделать следующее:

1 - используйте страницу PHP для аутентификации пользователя

2 - перенаправление на другую страницу PHP, содержащую ключ в URL-адресе, и iframe, ссылающийся на ваш статический контент в теле:

<iframe src="static/content.html" />

3 - Тогда в htaccess вы можете проверить ключ внутри HTTP_REFERER следующим образом:

RewriteEngine On
RewriteCond %{HTTP_REFERER} !AUTH_KEY
RewriteCond %{REQUEST_URI} ^/path/to/protected/page$
RewriteRule . - [F]

4 - Наконец, если вы хотите сделать его более динамичным и не использовать один и тот же KEY каждый раз, когда вы можете использовать rewrite map, как было предложено в ответ от Ignacio Vazquez-Abrams, или создать файл с использованием IP-адреса пользователя в качестве имени файла и проверить, файл существует с помощью REMOTE_ADDR, а затем удалите файл через некоторое время.

Но имейте в виду, что поведение iframe + HTTP_REFERER может отличаться от одного сеанса браузера к другому, а также REMOTE_ADDR, поэтому его ограничение...