Signer и TimeSigner для защиты данных от подделки

11.12.2025

При передаче данных через 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 используют системный ключ из настроек и не требуют дополнительной конфигурации. Это надёжный способ защитить любые передаваемые данные от модификации.

Опубликовано 1 неделю назад