При интеграции сторонних систем с веб-сервисами «1С:Предприятие» разработчики часто сталкиваются с техническим ограничением. Многие SOAP-клиенты (например, стандартный SoapClient в PHP, парсеры в Delphi, .NET или SoapUI) разделяют процесс работы на два этапа: сначала они отправляют простой HTTP GET-запрос для получения структуры описания веб-сервиса (WSDL), а уже затем выполняют POST-запросы для вызова конкретных методов.
Проблема заключается в том, что на этапе скачивания WSDL-схемы сторонние клиенты часто игнорируют параметры авторизации. В то же время платформа 1С не позволяет настроить частичную авторизацию в рамках одной публикации: если в базе заведен хотя бы один пользователь, GET-запрос к схеме вернет ошибку 401 Unauthorized. Если же прописать имя и пароль в файле default.vrd, то анонимными (под этим пользователем) станут абсолютно все запросы, включая бизнес-методы, что недопустимо с точки зрения безопасности.
Проанализируем ситуацию и разберем по шагам несколько надежных способов обойти это ограничение платформы 1С.
Этот способ основан на разделении одной публикации 1С на две: рабочую (с авторизацией) и вспомогательную (для чтения WSDL-схемы под системным пользователем с минимальными правами). Перенаправление настраивается силами веб-сервера Apache.
Рассмотрим алгоритм настройки подробно:
wsdl_view), которому доступен только запуск веб-сервиса без права чтения каких-либо конфиденциальных таблиц информационной базы.wsdl. Копируем в него файл конфигурации default.vrd из основного рабочего каталога.default.vrd в каталоге wsdl так, чтобы при обращении к нему происходила автоматическая авторизация под нашим служебным пользователем. Для этого в параметре подключения к информационной базе ib дописываем учетные данные:
ib="Srvr="Server1C";Ref="Trade";usr="wsdl_view";pwd="wsdl_view_pass";"
.htaccess. Нам нужно перенаправлять все GET-запросы, содержащие параметр ?wsdl, в нашу анонимную публикацию. Добавим следующие правила:
RewriteEngine On
RewriteCond %{QUERY_STRING} ^wsdl$
RewriteRule (.*) /wsdl/$1 [R=301,L]
wsdl создаем файл .htaccess, который будет отдавать ошибку 403 Forbidden на любые запросы, не содержащие параметр ?wsdl:
RewriteEngine On
RewriteCond %{QUERY_STRING} !^wsdl$
RewriteRule ^ - [R=403,L]
Если перед веб-сервером 1С установлен Nginx, задачу можно решить еще элегантнее — путем динамической подстановки заголовка авторизации «на лету» только для запросов схемы.
Выясним, как это работает. При получении запроса Nginx проверяет наличие GET-параметра wsdl. Если параметр присутствует, прокси-сервер самостоятельно добавляет в HTTP-заголовок данные базовой авторизации служебного пользователя, прежде чем передать запрос к 1С:
wsdl_view с паролем pass123.wsdl_view:pass123 в формат Base64. Получаем значение (например, d3NkbF92aWV3OnBhc3MxMjM=).
location /Base1C/ws/ {
proxy_pass http://127.0.0.1:8080/Base1C/ws/;
# Если в строке запроса присутствует wsdl, подставляем базовую авторизацию
if ($arg_wsdl) {
proxy_set_header Authorization "Basic d3NkbF92aWV3OnBhc3MxMjM=";
}
}
При такой схеме внешнему SOAP-клиенту вообще не нужно знать об авторизации для получения WSDL, а реальные вызовы методов будут требовать валидные учетные данные конкретного пользователя.
Многие современные SOAP-клиенты, которые не умеют отправлять заголовки Basic Auth при первом GET-запросе, тем не менее отлично справляются с разбором стандартного синтаксиса URL со встроенными учетными данными.
Попробуем предоставить клиенту ссылку в следующем формате:
http://wsdl_view:wsdl_view_pass@server.domain.ru/Base1C/ws/MyService.1cws?wsdl
При таком подходе веб-клиент самостоятельно извлечет логин и пароль из URI схемы и успешно авторизуется на веб-сервере 1С.
Проанализируем простейшую альтернативу, которая не требует никаких изменений в настройках веб-серверов. Если структура веб-сервиса (состав методов, типов и параметров) меняется нечасто, оптимальным решением будет однократное сохранение WSDL-схемы в локальный файл.
Выполним следующие шаги:
http://server/Base1C/ws/MyService.1cws?wsdl..wsdl (например, service.wsdl).
$client = new SoapClient("/path/to/local/service.wsdl", array(
'login' => "RealUser",
'password' => "RealPassword"
));
Важный нюанс: внутри сохраненного файла WSDL в самом конце в теге <soap:address location="..."> должен быть прописан корректный внешний URL-адрес вашего веб-сервиса 1С, на который клиент будет отправлять POST-запросы.