Как исправить ошибку HTTP 403 при вызове веб-сервиса 1С на сервере IIS?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Приветствуем вас! Сегодня мы разберем крайне популярную и неочевидную проблему, с которой часто сталкиваются разработчики и системные администраторы при интеграции мобильных приложений или внешних систем с базами данных 1С через веб-сервисы. Представьте ситуацию: вы успешно опубликовали веб-сервис на веб-сервере Microsoft IIS, настроили проброс портов (NAT) на сетевом оборудовании (например, с внешнего порта 9000 на внутренний порт 80 веб-сервера), и даже можете без проблем открыть XML-описание WSDL в браузере. Однако при попытке вызвать любой метод этого веб-сервиса из кода 1С система выдает ошибку HTTP Status 403 Forbidden.

Давайте подробно проанализируем эту ситуацию, выясним глубинную причину ее возникновения и рассмотрим все возможные пути решения — как программные (на стороне кода 1С), так и административные (на стороне IIS и сетевого оборудования).

Выясняем техническую причину: почему пропадает порт?

Когда мы инициализируем объект WSОпределения, передавая ему внешний адрес вида http://777.777.777.77:9000/mc_dms/ws/ws1.1cws?wsdl, платформа 1С отправляет GET-запрос на этот URL. Сетевой роутер перенаправляет этот запрос на внутренний сервер IIS (например, на локальный IP-адрес на стандартный порт 80).

Веб-сервер IIS обрабатывает этот запрос с помощью модуля расширения 1С (файла wsisapi.dll) и успешно возвращает XML-структуру WSDL-описания. На этом этапе все кажется рабочим. Но проблема кроется в самом содержимом WSDL-файла.

В самом конце полученного WSDL-файла находится секция описания точки подключения (эндпоинта), которая указывает клиенту, куда именно нужно отправлять последующие SOAP-запросы. Она выглядит примерно так:


<service name="central">
    <port name="centralSoap" binding="tns:centralSoapBinding">
        <soapbind:address location="http://777.777.777.77/mc_dms/ws/ws1.1cws" />
    </port>
</service>

Обратите внимание на параметр location внутри тега soapbind:address. В нем отсутствует порт 9000! Модуль 1С на стороне IIS генерирует этот адрес динамически, опрашивая переменные окружения веб-сервера. Поскольку IIS принял запрос на внутреннем порту 80, он считает, что порт по умолчанию (80) указывать в ссылке не нужно. Внешний порт 9000 полностью теряется.

Когда мы пытаемся создать WSПрокси и вызвать какой-либо метод (например, метод SetPhone), платформа 1С берет адрес хоста именно из этого тега location. В результате мобильный клиент или внешняя система пытается отправить POST-запрос по адресу http://777.777.777.77/mc_dms/ws/ws1.1cws (то есть на стандартный 80-й порт). Поскольку из внешней сети 80-й порт на этом сервере закрыт или занят другими службами, веб-сервер возвращает ошибку HTTP Status 403 Forbidden.

Решение 1. Программное переопределение адреса через статическую WS-ссылку

Рассмотрим первый способ обойти эту проблему непосредственно в коде 1С, если у нас нет возможности или прав администрировать веб-сервер IIS. Этот способ основан на использовании объекта метаданных WS-ссылки.

Если мы добавим WSDL-описание в конфигурацию 1С как статическую WS-ссылку (например, с именем WSСсылка1), мы сможем жестко переопределить адрес точки подключения при создании прокси-объекта. Метод СоздатьWSПрокси у статических ссылок имеет дополнительный параметр для явного указания интернет-адреса сервиса.

Давайте посмотрим на пример кода:


// Определяем пространство имен и имена сервиса и порта
URI = "central";
ВнешнийАдресПодключения = "http://777.777.777.77:9000/mc_dms/ws/ws1.1cws";

// Создаем прокси, передавая внешнюю точку подключения седьмым параметром
Прокси = WSСсылки.WSСсылка1.СоздатьWSПрокси(
    URI, 
    "central", 
    "centralSoap", 
    , 
    , 
    , 
    ВнешнийАдресПодключения
);

// Теперь вызов метода отработает корректно по правильному адресу с портом
ТекстОшибки = Прокси.SetPhone(Тел, Строка(ИД));

В этом сценарии, даже если в самом WSDL-файле адрес указан некорректно (без порта), платформа проигнорирует его и отправит все SOAP-запросы по адресу, указанному в переменной ВнешнийАдресПодключения. Это полностью решает проблему на стороне клиента.

Решение 2. Динамическая подмена WSDL на стороне клиента (для динамических соединений)

А что делать, если мы не можем использовать статические WS-ссылки в метаданных и нам необходимо подключаться динамически через WSОпределения? К сожалению, стандартный конструктор Новый WSПрокси не имеет параметра для переопределения точки подключения.

В таком случае мы можем применить обходной путь: скачать WSDL-описание как текстовый файл, программно заменить в нем неверный адрес на правильный с портом, сохранить на диск и скормить этот локальный файл объекту WSОпределения.

Разберем этот алгоритм по шагам на примере кода 1С:


// Шаг 1. Задаем исходные адреса
ВнешнийWSDL = "http://777.777.777.77:9000/mc_dms/ws/ws1.1cws?wsdl";
НеверныйАдрес = "http://777.777.777.77/mc_dms/ws/ws1.1cws";
ПравильныйАдрес = "http://777.777.777.77:9000/mc_dms/ws/ws1.1cws";

// Шаг 2. Скачиваем WSDL во временный файл
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xml");
Попытка
    КопироватьФайл(ВнешнийWSDL, ИмяВременногоФайла);
Исключение
    ВызватьИсключение "Не удалось загрузить WSDL-описание сервиса: " + ОписаниеОшибки();
КонецПопытки;

// Шаг 3. Читаем файл, находим и заменяем неверный адрес
ТекстWSDL = Новый ТекстовыйДокумент;
ТекстWSDL.Прочитать(ИмяВременногоФайла, КодировкаТекста.UTF8);
Содержимое = ТекстWSDL.ПолучитьТекст();

Если Найти(Содержимое, НеверныйАдрес) > 0 Тогда
    Содержимое = СтрЗаменить(Содержимое, НеверныйАдрес, ПравильныйАдрес);
    ТекстWSDL.УстановитьТекст(Содержимое);
    ТекстWSDL.Записать(ИмяВременногоФайла, КодировкаТекста.UTF8);
КонецЕсли;

// Шаг 4. Инициализируем WSОпределения из локально измененного файла
Определения = Новый WSОпределения(ИмяВременногоФайла, "mobile", "*********");

// Шаг 5. Создаем прокси. Теперь адрес внутри WSDL гарантированно содержит порт!
Прокси = Новый WSПрокси(Определения, "central", "central", "centralSoap");

// Удаляем временный файл после инициализации
УдалитьФайлы(ИмяВременногоФайла);

Этот способ универсален, так как позволяет динамически подключаться к любым внешним сервисам, полностью контролируя корректность генерируемого адреса эндпоинта на стороне клиента.

Решение 3. Выравнивание портов на стороне IIS (Bindings)

Если у вас есть доступ к администрированию веб-сервера IIS и сетевого оборудования, самым правильным решением будет устранение первопричины на уровне сети.

Вместо того чтобы настраивать на роутере трансляцию портов со сменой значения (например, внешний 9000 перенаправлять на внутренний 80), настройте проброс портов "один в один" — 9000 -> 9000.

Давайте выполним настройку в IIS по шагам:

  1. Откройте диспетчер служб IIS (Internet Information Services Manager).
  2. В дереве подключений слева разверните ваш сервер и перейдите в раздел Сайты (Sites).
  3. Выберите сайт, на котором опубликована информационная база 1С (по умолчанию это Default Web Site).
  4. В панели "Действия" (справа) нажмите на ссылку Привязки... (Bindings...).
  5. В открывшемся окне нажмите кнопку Добавить... (Add...).
  6. В поле "Тип" выберите http.
  7. В поле "Порт" укажите внешний порт, который вы пробросили на роутере (например, 9000). Поле "IP-адрес" можно оставить как "Все неназначенные".
  8. Нажмите "ОК" и перезапустите веб-сайт.

Теперь, когда внешний запрос будет приходить на порт 9000, веб-сервер IIS примет его именно на порту 9000. В результате модуль расширения 1С автоматически сгенерирует корректный адрес внутри WSDL, добавив туда двоеточие и номер порта. Никаких доработок кода 1С в этом случае не потребуется!

Решение 4. Использование модуля URL Rewrite для исправления WSDL "на лету"

Бывают ситуации, когда изменить порты в привязках IIS невозможно (например, если порт жестко зарезервирован под другие нужды или сеть имеет сложную структуру). В этом случае мы можем заставить IIS автоматически подменять некорректный адрес в тексте WSDL перед тем, как отдать его клиенту.

Для этого используется официальный модуль расширения URL Rewrite для IIS. С его помощью настраивается исходящее правило (Outbound Rule), которое будет сканировать XML-ответы сервера 1С и заменять адрес без порта на адрес с портом.

Давайте разберем, как это настроить:

  1. Установите модуль URL Rewrite на сервер IIS.
  2. Откройте диспетчер IIS, выберите ваш сайт и дважды щелкните на иконку URL Rewrite.
  3. В правой панели выберите Add Rule(s)..., затем в разделе Outbound Rules выберите Blank Rule (пустое правило).
  4. Задайте правилу понятное имя, например, Fix WSDL Port.
  5. В секции Match укажите фильтр по содержимому (Response Content Type Matching). Нам нужны только ответы с типом text/xml или application/xml.
  6. В секции Match Rules задайте шаблон поиска. Мы ищем строку http://777.777.777.77/mc_dms/ws/ws1.1cws.
  7. В секции Action выберите тип действия Rewrite и в поле Value укажите правильное значение с портом: http://777.777.777.77:9000/mc_dms/ws/ws1.1cws.
  8. Сохраните изменения и примените правило.

Этот метод чрезвычайно удобен тем, что он абсолютно прозрачен для любых клиентов (будь то мобильное приложение 1С, конфигурация на другой платформе или сторонний софт). Клиент всегда будет скачивать WSDL с уже правильным адресом точки подключения.

Решение 5. Настройка обратного прокси (Reverse Proxy)

Если перед вашим сервером IIS стоит прокси-сервер (например, Nginx, Apache или HAProxy), который принимает внешние запросы и перенаправляет их на IIS, проблема решается корректной передачей заголовков.

Очень часто администраторы настраивают Nginx так, что он передает на бэкенд только чистое имя хоста без оригинального порта. Чтобы IIS понимал, какой именно порт использовал клиент, необходимо в конфигурации прокси-сервера (например, Nginx) явно указать передачу оригинального заголовка хоста:

proxy_set_header Host $http_host;

Использование переменной $http_host вместо стандартной $host гарантирует, что имя хоста будет передано вместе с внешним портом. Если же ваш прокси работает по протоколу HTTPS, а IIS внутри сети работает по HTTP, обязательно передавайте заголовок протокола:


proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Port 443;

Это позволит платформе 1С генерировать ссылки с правильным протоколом https:// в описании веб-сервисов.

Мы подробно разобрали, почему возникает ошибка HTTP 403 при работе с веб-сервисами 1С на IIS, и рассмотрели целых пять эффективных способов борьбы с этой проблемой. Выбор конкретного метода зависит от вашей роли в проекте и доступных прав доступа. Если вы разработчик 1С и не имеете доступа к серверу — используйте переопределение адреса через статические ссылки или динамическую подмену XML. Если вы системный администратор — настройте привязки в IIS или правила URL Rewrite. Успешной вам интеграции!

← На главную