Управляем безопасностью сайта
В этой версии добавлен функционал для управления безопасностью сайта. Большая часть доработок касается работы с CSRF токенами. Кто не знает, что такое CSRF токены и для чего они нужны, идёт просвящаться. Так вот, данный функционал необходим для защиты вашего сайта от атак с межсайтовой подделкой запросов. Кстати, админка MODX использует эту защиту — для каждого запроса добавляется токен HTTP_MODAUTH
.
CSRF токены
Библиотека modHelpers автоматически генерирует CSRF токен при инициализации (при условии, что включен механизм сессий). Этот токен используется для проверки факта, что запрос поступил от пользователя с сайта. Для создания и получения токена используется функция csrf_token()
. Также его можно переформировать заново, если передать в функцию первым аргументом TRUE.
Внимание!
В примерах используется шаблонизатор Fenom. Чтобы запускать функции modHelpers в разметке, необходимо разрешить Fenom использовать PHP. Для этого нужно включить системную настройку pdotools_fenom_php
.
Использование токена в HTML формах
Разместите в форме скрытый инпут с именем csrf_token
. Сделать это можно через вызов функции-хелпера csrf_field()
.
<form method="POST" action="profile"> {csrf_field()} <!-- <input type="hidden" name="csrf_token" value="sf7Y5wgC01vaSck2rc"> --> ... </form>
Использование в заголовках запроса
Ещё один способ передать токен — через специальный заголовок X-CSRF-TOKEN
. Для этого можно использовать, например, HTML тег МЕТА в шаблоне:
<meta name="csrf-token" content="{csrf_token()}">
Можно использовать хелпер csrf_meta()
, который вставит готовый код тега в шаблон.
Дальше нужно добавить токен к заголовкам запроса. Вот пример для jQuery:
$.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } });
Ещё вариант — вместо тега META вставлять в шаблон яваскрипт переменную и её добавлять в заголовки. It's up to you.
Проверка токена
После того, как вы добавили токен в запрос, нужно его проверить. Если у вас установлен компонент Middlewares
, то проверку можно делать в глобальном посреднике. Если нет, то место вы можете выбрать сами. Это может быть класс, плагин или сниппет. Вот примеры проверок:
if (request()->checkCsrfToken()) { // Токен существует и соответствует токену в сессии }
Условия могут быть разными
// Валидация проходит только для залогиненного пользователя if (is_auth() && request()->checkCsrfToken() { // Выполнить запрашиваемые действия } else { // Запрос отклонён abort(); } // Исключение страниц из проверки. Не проверять страницы с адресом site.ru/pages/1, site.ru/pages/2 и т.д. if (!request()->match('pages/*') && request()->checkCsrfToken() {...} // Проверять только POST запросы if (request()->isMethod('POST') && request()->checkCsrfToken() {...}
Просто проверить наличие токена в запросе:
if (request()->getCsrfToken()) { // Токен есть }
Проверка ботов
Ещё одна доработка позволяет проверять кем выполнен запрос — ботом или человеком. Логика очень простая — в системной настройке указываются паттерны юзер-агентов ботов, спайдеров и т.п. Ну а дальше проверяется юзер-агент запроса. Эта возможность будет полезна, если нужно что-то скрыть от роботов. Например, какие-нибудь ссылки или кнопки у формы. Альтернатива всяким nofollow и noindex.
{if request()->isBot()} <p>Информация для роботов.</p> {else} <a href="url">Ссылка только для пользователей</a> {/if}
Заключение
Ну и последний пункт из списка изменений — изменение приоритета загрузки. Я установил его на -1000, чтобы библиотека грузилась самой первой. Теперь всё. В ближайшее время выйдет обновление Middlewares
. Хочу записать видео о новых возможностях этого компонента. Надеюсь, получится.
Комментарии ()
Вы должны авторизоваться, чтобы оставлять комментарии.
никогда не произведет вхождение, потому что сессия пустая.
Возможно в Middlewares и стартуется сессия автоматом, но как быть тогда с:
У меня странная ситуация получилась. Прописал как в данном мануале {csrf_meta()} в чанке, где все что касается тега head. Смотрю на сайте даже все создалось и сгенерировался токен. Потом создал плагин на событие OnWebPagePrerender и прописал такое:
Смотрю в журнале ошибок и вижу там Token:
Тоесть Пустой. Лезу на сервер, смотрю в папке sessions а там 0 файлов сессий.
Запускаю свой проверочный файл где я сам вручную делаю session_start() — все нормально, файлы создаются.
Ничего понять не могу.
modhelpers-3.3.0-beta
Судя по всему вы не понимаете механизм токенов. Если коротко — токен не нужно проверять в каждом запросе. Он используется как подпись для важного действия. Как правило когда приходит форма или ajax запрос и нужно выполнить определённые манипуляции.
Как работает.
1. Токен генерится в плагине modHelpers.
2. Проверка токена идет или по специальному заголовку или по данным формы (см. статью). Мета тег нужен для генерации заголовка для ajax запросов, чтобы не морочится с добавлением токена к каждой форме. Прописал один раз и всё. Вместо МЕТА тега можно указать javascript переменную.
А затем его указать
Таким образом подписывается каждый API запрос. Если Вы их не используете, то нужно просто подписать форму через csrf_field(), а META тег можно не указывать.
Я не использую компонент Middlewares.
Уже создал плагин на событие OnHandleRequest и все равно токена нет.
Хотя в хроме я смотрю x-csrf-token в Request Headers не NULL а ytGyMX8F1e2bnEslPFu7qNU3xGRuEUMRwlts1N9L
П.С. Надеюсь, Вы через ajax делали запрос.
Вызываю форму в чанке вот так:
Сам чанк tpl.AjaxForm:
Сниппет csrf:
Все же так?