В современной разработке интеграций на платформе 1С:Предприятие вопросы безопасности стоят на первом месте. Использование протокола HTTPS для веб-сервисов стало стандартом. Однако часто возникает ситуация, когда разработчик создает сервис с валидным, подписанным удостоверяющим центром сертификатом, но при попытке подключения из 1С получает ошибку: "Удаленный узел не прошел проверку".
Традиционный, но устаревший подход решения этой проблемы заключался в выгрузке сертификата в файл и добавлении его в специальный файл настроек платформы — cacert.pem. Это крайне неудобно, если пользователей много, их квалификация низка, а сертификат на сервере периодически обновляется. Разберем, как реализовать подключение программно, используя системные средства Windows, и избежать "танцев с бубном" на клиентских машинах.
Рассмотрим ситуацию, описанную автором. Имеется веб-сервис, защищенный официальным SSL-сертификатом. Задача — подключиться к нему из клиентского приложения 1С. В попытке сделать соединение максимально "правильным", разработчики часто допускают ошибку в конструкторе защищенного соединения.
Посмотрим на типичный ошибочный код:
Попытка
SSL = Новый ЗащищенноеСоединениеOpenSSL(
Новый СертификатКлиентаWindows(СпособВыбораСертификатаWindows.Авто),
Новый СертификатыУдостоверяющихЦентровWindows
);
Определения = Новый WSОпределения("https://example.com/service.wsdl", , , , SSL);
// Дальнейший код...
Исключение
// Ошибка: Удаленный узел не прошел проверку
КонецПопытки;
В чем здесь проблема? Разберем параметры конструктора ЗащищенноеСоединениеOpenSSL.
Новый СертификатКлиентаWindows, мы заставляем 1С искать личный сертификат пользователя, которого у него может и не быть, или пытаться отправить что-то некорректное.Начиная с версий платформы 8.3.7, 1С научилась полноценно работать с системным хранилищем сертификатов Windows. Это значит, что нам больше не нужно вручную редактировать файл cacert.pem, если сертификат сервера выдан доверенным центром (например, GlobalSign, Let's Encrypt, DigiCert и т.д.), и этот центр есть в списке доверенных в Windows.
Чтобы заставить 1С доверять сертификату сервера, используя базу Windows, и при этом не требовать сертификат от клиента, код должен выглядеть следующим образом:
// Создаем защищенное соединение.
// Первый параметр (клиентский сертификат) ставим Неопределено, так как сервер его не требует.
// Второй параметр указывает использовать системное хранилище Windows для проверки валидности сертификата сервера.
SSL = Новый ЗащищенноеСоединениеOpenSSL(Неопределено, Новый СертификатыУдостоверяющихЦентровWindows());
Пользователь = "user@mail.ru";
Пароль = "password";
Попытка
// Важно: передаем SSL-контекст уже на этапе получения Определений (WSDL)
Определения = Новый WSОпределения("https://myservice.com/trade?wsdl", Пользователь, Пароль, , SSL);
Прокси = Новый WSПрокси(Определения, "NamespaceURI", "ServiceName", "PortName");
// Также назначаем пользователя и пароль для самого прокси
Прокси.Пользователь = Пользователь;
Прокси.Пароль = Пароль;
// Если требуется, назначаем тот же SSL контекст и прокси-объекту (обычно наследуется из определений, но для надежности)
Прокси.sslЗащищенноеСоединение = SSL;
Результат = Прокси.МойМетод();
Исключение
Сообщить("Ошибка подключения: " + ОписаниеОшибки());
КонецПопытки;
Даже при правильном коде вы можете столкнуться с ошибкой проверки сертификата. Разберем основные причины, которые не зависят от кода 1С, но влияют на результат.
1. Промежуточные сертификаты (Intermediate Certificates)
Это самая частая причина. Цепочка доверия выглядит так: Ваш сертификат -> Промежуточный сертификат -> Корневой сертификат (в Windows). Браузеры (Chrome, Firefox) умеют автоматически скачивать недостающие промежуточные сертификаты или брать их из кэша. 1С этого не делает. Платформа ожидает, что веб-сервер пришлет полную цепочку сертификатов (Full Chain).
Если веб-сервер (Apache, IIS, Nginx) настроен неправильно и отдает только конечный сертификат домена, 1С не сможет построить цепочку до корневого центра и выдаст ошибку проверки, даже если сертификат валиден. Проверить это можно онлайн-утилитами (SSL Checker), которые покажут, отдается ли "Chain" полностью.
2. Устаревшие операционные системы клиентов
Объект СертификатыУдостоверяющихЦентровWindows обращается к ОС. Если у клиента стоит старая Windows 7 без обновлений, в ней может просто не быть свежих корневых сертификатов (например, новых корней Let's Encrypt). В этом случае поможет только обновление Windows или ручная установка корневого сертификата в систему.
3. Протоколы шифрования (TLS)
Современные сервисы часто отключают устаревшие протоколы SSLv3, TLS 1.0 и TLS 1.1. Если платформа 1С старая, она может пытаться соединиться по устаревшему протоколу. В свежих версиях платформы (8.3.10+) по умолчанию используется TLS 1.2, что решает проблему.
Если WSОпределения сразу вызывает ошибку, бывает сложно понять причину. Для диагностики рекомендуем использовать объект HTTPСоединение, так как он позволяет более гибко проверять доступность узла перед работой с SOAP.
Пример проверочного кода:
SSL = Новый ЗащищенноеСоединениеOpenSSL(Неопределено, Новый СертификатыУдостоверяющихЦентровWindows());
Соединение = Новый HTTPСоединение("myservice.com", 443, , , , , SSL);
Запрос = Новый HTTPЗапрос("/trade?wsdl");
Попытка
Ответ = Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда
Сообщить("Соединение успешно установлено! Сертификат принят.");
Иначе
Сообщить("Соединение есть, но вернулся код: " + Ответ.КодСостояния);
КонецЕсли;
Исключение
Сообщить("Ошибка SSL или сети: " + ОписаниеОшибки());
КонецПопытки;
Если по каким-то причинам использование системного хранилища невозможно (например, Linux-сервер 1С без графической оболочки и настроенных сертификатов ca-certificates), можно использовать сертификат из файла. Но для массового распространения обработки клиентам этот метод менее удобен, так как требует передачи файла .pem или .cer вместе с обработкой.
// В этом случае сертификат сервера (или CA) должен лежать на диске
СертификатФайл = Новый СертификатКлиентаФайл("C:\Certificates\server.cer");
// Обратите внимание: класс СертификатКлиентаФайл используется здесь для передачи в OpenSSL,
// но логика использования зависит от того, передаем мы его как клиентский или как доверенный.
// Однако для проверки сервера правильнее использовать ca-bundle и указывать его путь,
// но в 1С чаще просто полагаются на системное хранилище.
Для массового сервиса для "неизвестных" клиентов лучше всего придерживаться стратегии:
Новый СертификатыУдостоверяющихЦентровWindows().Неопределено), если это не требуется архитектурой безопасности.