Обсуждение
Если вы решите хранить загружаемые файлы содержимого высокого уровня непосредственно в файловой системе , лучше всего держать их вне webroot .
Затем вашему приложению придется решить проблему создания URL-адресов (при необходимости, кодирования URL) для содержимого (PDF-файлы, документы Word, песни и т. Д.).
Как правило, это может быть достигнуто с помощью запроса для получения пути к файлу, а затем с помощью пути к файлу для отправки содержимого пользователю (с помощью header()
и т. Д.), Когда он или она нажимает на привязку (все при этом пользователь никогда не увидит истинный путь к файлу на стороне сервера).
Если вы не хотите, чтобы пользователь A обменивался URL-адресами для загружаемого контента с высокой ценностью для пользователя B , то ваше приложение должно каким-то образом сделать ссылки исключительно привязанными к пользователю A . Что можно сделать? С чего мне начать?
Очевидно, вы хотите убедиться, что пользователь A вошел в систему во время сеанса, прежде чем он или она сможет загрузить файл. не так очевидно состоит в том, как запретить вошедшему в систему пользователю B использовать URL-адрес, отправленный пользователем A (пользователю B ) для загрузки A цифрового контента.
Использование $_SESSION
для хранения зарегистрированного идентификатора пользователя (числовое или строковое) и выполнение этой части возможного запроса (при условии, что контент привязан к покупкам пользователя или чем-то еще) предотвратит вход в систему пользователя B при загрузке вещей, которые они не приобрели , но вы по-прежнему будете подвергаться попаданию ресурса для обработки пустого набора SQL для элементов, которые у них не куплены . Это звучит как хороший второй шаг.
А как насчет первого шага? Есть ли что-то, что может предотвратить необходимость делать запрос для начала?
Хорошо, давайте посмотрим. В HTML-формах можно использовать токен XSRF в скрытом поле, чтобы убедиться, что отправленная форма действительно возникла с веб-сервера, который получает запрос POST / GET. Один токен используется для всей формы.
При наличии страницы пользовательских вещей, которые нужно загрузить (якоря), можно вставить один токен (тот же токен, но разный для каждого запроса страницы) в атрибут href
каждого якоря в виде параметра строки запроса и сохранить копия этого токена в $_SESSION
.
Теперь, когда вошедший в систему пользователь B пытается использовать вошедшего в систему пользователя A shared URL, все завершается неудачно, потому что user A и user B имеют разные сеансы (или вообще без сеансов) и, следовательно, разные токены. Другими словами: «Моя ссылка такая же, как ваша, но другая». Якоря будут привязаны к сеансу, а не только к странице, пользователю или контенту.
С этой системой PHP может определить, является ли запрос контента допустимым, не задействуя базу данных (сравнивая отправленный токен с токеном в $_SESSION
). Более того, в $_SESSION
может быть установлен лимит времени для ограничения продолжительности / времени жизни действующего токена XSRF. Просто используйте функцию time()
и базовую математику. Шестьдесят минут могут быть идеальным временем жизни токена для якоря в этой ситуации. Пройдите вход пользователя еще раз, если токен для привязанного якоря истек.
Резюме
Если вы используете файлы в файловой системе и сохраняете пути в базе данных, убедитесь, что вы делаете следующее (как минимум) тоже.
- Примените надлежащие права доступа к файлу для вашего каталога содержимого (вне webroot).
- Использовать случайные имена для загружаемых файлов.
- Проверьте наличие повторяющихся имен файлов перед сохранением файла из загрузки.
- Только зарегистрированные пользователи должны иметь возможность загружать высококачественное содержимое.
- Наличие эффективной
$_SESSION
системы, которая препятствует фиксации сеанса.
- Сделать URL-адреса для загружаемого контента высокой ценности уникальными для каждой страницы с помощью хешированных маркеров XSRF.
- Токены XSRF покрывают больше сценариев, когда они имеют срок службы терминала.
- Выполнение SQL-запросов для пользовательского контента на основе зарегистрированного идентификатора пользователя, а не только продукта.
- Фильтрация и проверка всех пользовательских данных.
- Использовать подготовленные операторы с запросами SQL.