Signer и TimeSigner для защиты данных от подделки
При передаче данных через URL, формы или AJAX необходимо гарантировать их целостность. Стандартные проверки легко обойти, а хранение данных в сессии усложняет архитектуру. Классы Bitrix\Main\Security\Sign\Signer и TimeSigner решают эту задачу криптографической подписью.
Базовая подпись через Signer
Класс Signer создаёт подпись данных на основе HMAC и системного ключа:
use Bitrix\Main\Security\Sign\Signer;
use Bitrix\Main\Security\Sign\BadSignatureException;
$signer = new Signer();
// Подписываем данные
$data = 'user_id=15&action=delete';
$signed = $signer->sign($data);
// Результат: "user_id=15&action=delete.a1b2c3d4e5..."
// Проверяем и извлекаем данные
try {
$original = $signer->unsign($signed);
// $original === 'user_id=15&action=delete'
} catch (BadSignatureException $e) {
// Данные были изменены
}
Использование salt для изоляции контекстов
Параметр salt позволяет создавать независимые подписи для разных сценариев:
use Bitrix\Main\Security\Sign\Signer;
$signer = new Signer();
// Подписи с разными salt несовместимы
$tokenA = $signer->sign('data', 'context_a');
$tokenB = $signer->sign('data', 'context_b');
// Проверка требует тот же salt
$signer->unsign($tokenA, 'context_a'); // OK
$signer->unsign($tokenA, 'context_b'); // BadSignatureException
Подпись с ограничением времени через TimeSigner
TimeSigner добавляет срок действия подписи — критически важно для одноразовых ссылок:
use Bitrix\Main\Security\Sign\TimeSigner;
$timeSigner = new TimeSigner();
// Ссылка для сброса пароля, действует 1 час
$token = $timeSigner->sign('user_id=42', '+1 hour');
// Подтверждение email, действует 24 часа
$emailToken = $timeSigner->sign('email=test@example.com', '+1 day');
// Можно указать точный timestamp
$exactToken = $timeSigner->sign('data', strtotime('2025-12-31 23:59:59'));
При проверке автоматически контролируется срок:
try {
$data = $timeSigner->unsign($token);
} catch (BadSignatureException $e) {
// "Signature timestamp expired" — время истекло
// или "Signature does not match" — данные изменены
}
Практический пример: защищённая ссылка отписки
use Bitrix\Main\Security\Sign\BadSignatureException;
use Bitrix\Main\Security\Sign\TimeSigner;
use Bitrix\Main\Web\Json;
// Генерация ссылки
$timeSigner = new TimeSigner();
$payload = Json::encode(['user_id' => 15, 'mailing_id' => 7]);
$token = $timeSigner->sign($payload, '+7 days', 'unsubscribe');
$url = '/unsubscribe/?token=' . urlencode($token);
$request = \Bitrix\Main\Context::getCurrent()->getRequest();
// Обработка перехода
try {
$data = Json::decode(
$timeSigner->unsign($request->get('token'), 'unsubscribe')
);
// Безопасно отписываем пользователя
} catch (BadSignatureException $e) {
// Ссылка недействительна или истекла
}
Классы Signer и TimeSigner используют системный ключ из настроек и не требуют дополнительной конфигурации. Это надёжный способ защитить любые передаваемые данные от модификации.