При разработке интеграций через 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С. Суть заключается в том, что мы разрешаем доступ к сервису без стандартной авторизации на уровне веб-сервера, а проверку логина и пароля выполняем программно в теле метода 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.
Рассмотрим ситуацию, когда мы не хотим менять логику авторизации в самой 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.
Если используется только 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>
Если ваша публикация работает на IIS, решение будет иным. В файле web.config, который находится в папке публикации, используется секция <httpErrors>.
Рассмотрим по шагам:
web.config.<system.webServer>.
<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С и использовать ваш файл.
Выбор метода зависит от ваших архитектурных задач:
Base64) крайне важно соблюдать кодировку UTF-8, иначе логины или пароли с кириллицей будут распознаны неверно.Используя эти подходы, вы сможете обеспечить профессиональный уровень взаимодействия вашего API с внешними системами, соблюдая стандарты обмена данными в формате JSON.