Как вернуть свой JSON-ответ при ошибке авторизации 401 или 403 в HTTP-сервисе 1С?

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

При разработке интеграций через HTTP-сервисы в 1С разработчики часто сталкиваются со стандартным поведением веб-серверов (Apache или IIS). Если в запросе переданы неверные данные для Authorization Basic, веб-сервер или модуль расширения 1С перехватывают запрос еще до того, как управление попадет в программный код 1С. В результате клиент получает стандартную HTML-страницу с ошибкой 401 Unauthorized или 403 Forbidden, в то время как современным API требуется ответ в формате JSON. Рассмотрим, как обойти это ограничение и реализовать выдачу собственного текста ошибки.

Причина возникновения проблемы

Проанализируем ситуацию: когда мы публикуем HTTP-сервис, 1С по умолчанию полагается на механизмы авторизации платформы. Как только запрос поступает на Apache, модуль mod_1c проверяет заголовок Authorization. Если логин или пароль неверны, платформа сразу обрывает соединение и возвращает статус 401/403. Код метода HTTP-сервиса при этом даже не начинает выполняться. Чтобы обойти это, нам нужно либо перехватить ответ на уровне веб-сервера, либо заставить платформу пропустить запрос внутрь 1С без предварительной проверки.

Способ 1. Публикация под «дефолтным» пользователем и ручная авторизация

Этот метод считается самым гибким и надежным с точки зрения логики 1С. Суть заключается в том, что мы разрешаем доступ к сервису без стандартной авторизации на уровне веб-сервера, а проверку логина и пароля выполняем программно в теле метода HTTP-сервиса.

Шаг 1. Настройка файла публикации (.vrd)

Разберем, что нужно изменить в файле default.vrd. Нам необходимо указать конкретного пользователя с минимальными правами, под которым система будет «впускать» все входящие запросы. В секции <httpServices> или в общих параметрах укажите параметры ib (строка соединения), где прописаны Usr и Pwd. Либо используйте анонимный доступ, если это позволяет инфраструктура.

Шаг 2. Программный разбор заголовка Authorization

Теперь, когда запрос попадает в наш метод 1С, проанализируем заголовок самостоятельно. Рассмотрим пример кода для разбора Basic авторизации:


Функция ДанныеЗапроса(Запрос)
    
    ЗаголовокАвторизации = Запрос.Заголовки.Получить("Authorization");
    
    Если ЗаголовокАвторизации = Неопределено Тогда
        Возврат СформироватьОтветОшибки();
    КонецЕсли;
    
    // Удаляем префикс "Basic "
    Base64ЛогинПароль = СтрЗаменить(ЗаголовокАвторизации, "Basic ", "");
    
    // Декодируем строку
    ДвоичныеДанныеДекодированные = СредстваКриптографии.РасшифроватьBase64(Base64ЛогинПароль);
    СтрокаДанных = ПолучитьСтрокуИзДвоичныхДанных(ДвоичныеДанныеДекодированные, КодировкаТекста.UTF8);
    
    // Разделяем логин и пароль по символу ":"
    МассивДанных = СтрРазделить(СтрокаДанных, ":");
    Если МассивДанных.Количество() < 2 Тогда
        Возврат СформироватьОтветОшибки();
    КонецЕсли;
    
    Логин = МассивДанных[0];
    Пароль = МассивДанных[1];
    
    // Проверяем пользователя в системе
    Если НЕ ПользовательВалиден(Логин, Пароль) Тогда
        Возврат СформироватьОтветОшибки();
    КонецЕсли;
    
    // Если всё хорошо, продолжаем основную логику...
    
КонецФункции

Функция СформироватьОтветОшибки()
    Ответ = Новый HTTPСервисОтвет(401);
    Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
    
    СтруктураОшибки = Новый Структура;
    СтруктураОшибки.Вставить("success", Ложь);
    СтруктураОшибки.Вставить("error", "Неверный логин или пароль");
    СтруктураОшибки.Вставить("code", 401);
    
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON, СтруктураОшибки);
    
    Ответ.УстановитьТелоИзСтроки(ЗаписьJSON.Закрыть());
    Возврат Ответ;
КонецФункции

В этом случае мы полностью контролируем тело ответа и можем вернуть любой JSON, который требует спецификация нашего API.

Способ 2. Использование Nginx как обратного прокси

Рассмотрим ситуацию, когда мы не хотим менять логику авторизации в самой 1С, но нам нужно подменить ответ веб-сервера. Для этого перед Apache устанавливается Nginx. Он будет выступать в роли «щита» и интерпретатора ответов.

Выясним причину, почему это эффективно: Nginx умеет перехватывать ответы с определенным кодом от бэкенда (в нашем случае Apache + 1С) и заменять их на свои. В конфигурационном файле Nginx это реализуется с помощью директивы proxy_intercept_errors.

Посмотрим на пример конфигурации Nginx:


server {
    listen 80;
    server_name my1c-service.ru;

    location / {
        proxy_pass http://127.0.0.1:8080; # Адрес вашего Apache
        proxy_intercept_errors on;
        error_page 401 403 = @custom_error;
    }

    location @custom_error {
        default_type application/json;
        return 401 '{"status": false, "message": "Доступ запрещен. Ошибка авторизации.", "code": 401}';
    }
}

Преимущество этого метода в том, что 1С работает в штатном режиме, а подменой формата занимается высокопроизводительный прокси-сервер. Однако помните, что при 401 ошибке браузеры могут всё равно выводить системное окно ввода пароля, если вы не измените заголовок WWW-Authenticate.

Способ 3. Настройка Apache (ErrorDocument)

Если используется только Apache, мы можем использовать встроенную директиву ErrorDocument. Это позволяет указать текст, который будет возвращен клиенту при возникновении ошибки.

Проанализируем настройки в файле httpd.conf или .htaccess. Мы можем прописать JSON-строку прямо в конфигурации:

ErrorDocument 401 "{\"error\": \"Unauthorized\", \"code\": 401}"

Важный нюанс: Apache по умолчанию может отдавать такой ответ как text/html. Чтобы клиент (например, мобильное приложение или другой сервис) корректно распознал JSON, необходимо принудительно установить заголовок через модуль mod_headers:


<Location "/your_base/hs/">
    Header always set Content-Type "application/json"
    ErrorDocument 401 "{\"success\": false, \"message\": \"Authentication failed\"}"
</Location>

Способ 4. Настройка IIS (для Windows-серверов)

Если ваша публикация работает на IIS, решение будет иным. В файле web.config, который находится в папке публикации, используется секция <httpErrors>.

Рассмотрим по шагам:

  1. Откройте web.config.
  2. Найдите или создайте секцию <system.webServer>.
  3. Добавьте настройку переопределения ошибок:

<configuration>
   <system.webServer>
      <httpErrors errorMode="Custom" existingResponse="Replace">
         <remove statusCode="401" subStatusCode="-1" />
         <error statusCode="401" path="error401.json" responseMode="File" />
      </httpErrors>
   </system.webServer>
</configuration>

В данном случае, при возникновении ошибки 401, IIS возьмет содержимое файла error401.json и отправит его клиенту. Параметр existingResponse="Replace" критически важен, так как он заставляет сервер игнорировать стандартный ответ от модуля 1С и использовать ваш файл.

Резюме и рекомендации

Выбор метода зависит от ваших архитектурных задач:

Используя эти подходы, вы сможете обеспечить профессиональный уровень взаимодействия вашего API с внешними системами, соблюдая стандарты обмена данными в формате JSON.

← На главную