Отправка клиентского SSL-сертификата в PHP без cURL: пример с stream_context_create для Сбер ID

24.01.2025 ≈ 2 минуты. 21 показ 1 дочитывание

Клиентские SSL-сертификаты используются для идентификации клиента или пользователя и аутентификации клиента на сервере. Обычно в таком случае используется двухфакторная идентификация – через логин/пароль, а также через сертификат.

Необходимость в передаче сертификата в запросе появилась при добавлении возможности входа на сайт через Сбер ID в модуль Входа по ID для 1С-Битрикс.

Для запросов к API Сбер ID требуется передать помимо ключей еще и сертификат. В интернете навалом примеров использования для этого curl. Но эта библиотека может быть не установлена на сервере, а разработку модулей стараемся делать таким образом, чтобы как можно меньше приходилось что-то настраивать и устанавливать дополнительно. В таком случае меньше обращений в поддержку за помощью.

Поэтому приведу пример передачи сертификата без curl. Так как в инете не нашел такой информации, только отдельные части, наводящие на решение.

Распаковка контейнера с сертификатом

Сбер дает скачать запароленный контейнер с сертификатом и приватным ключом в формате PKCS#12. Первым делом нужно извлечь эти данные из контейнера.

$containerContent = file_get_contents($arFile['tmp_name']);

if (!function_exists('openssl_pkcs12_read')) {
    throw new \BXmaker\AuthID\Exception\BaseException(self::getMessage(
        'ERROR_OPENSSL_LIBRARY_NOT_FOUND'
    ));
}

if (!openssl_pkcs12_read($containerContent, $certificates, $filePassword)) {
    throw new \BXmaker\AuthID\Exception\BaseException(self::getMessage(
        'ERROR_CERTIFICATE_FILE_READ'
    ));
}

\Bitrix\Main\IO\File::putFileContents(
    $serviceDir . '/client.crt',
    $certificates['cert'] . implode('', $certificates['extracerts'])
);

\Bitrix\Main\IO\File::putFileContents(
    $serviceDir . '/private.key',
    $certificates['pkey']
);

Запрос с передачей клиентского сертификата методом POST или GET

Все что нужно сделать - дополнить опции контекста запроса данными о путях до файлов сертификата и приватного ключа. Передаются они в метод - stream_context_create подробнее о методе - https://www.php.net/manual/ru/function.stream-context-create.php

В реализации для 1С-Битрикс это будет выглядеть примерно так

$oHttpClient = new \Bitrix\Main\Web\HttpClient();
$oHttpClient->setTimeout(10);
$oHttpClient->setStreamTimeout(10);
//$oHttpClient->disableSslVerification();


$oHttpClient->setContextOptions([
    'ssl' => [
        'verify_peer' => false,
        'verify_peer_name' => false,
        'allow_self_signed' => true,
        'local_cert' => '/storage/client.crt',
        'local_pk' => '/storage/private.key',
    ]
]);

$oHttpClient->get('https://oauth.sber.ru/api/v2/auth/completed');

Обратно к списку