gifts2017

Маленький ВЕБ-сервис с большими возможностями

Опубликовал Денис Лазарев (irreal) в раздел Обмен - Интеграция с WEB

Представьте, что у вас есть несколько баз данных, похожих и не похожих друг на друга, возможно, разделенных просторами интернета. Намерение, например, что-то одновременно поменять в них, записать новый элемент справочника, снять однотипные отчеты упирается в волну неприятного предвкушения полазить по терминалкам ради захода в каждую базу, если не предусмотрено средств работы с базами из одного места. ВЕБ-сервисы предоставляют подходящий для интернета транспорт для передачи данных и локализуют ресурсоемкие COM-соединения в пределах связки каждой пары сервер 1С и веб-сервер.

При этом для использования в рамках платформы 1С совершенно не обязательно углубляться в собственную структуру веб-сервиса, разрабатывать его объектную модель и интерфейсы. Достаточно выставить через сервис фунцию вида CmdExec(ParamStructure: string):string и гонять между базами строки, получаемые функцией ЗначениеВСтрокуВнутр(). Если в одном из полей структуры передавать код обработки данных на языке 1С, получаем всемогущий инструмент. Итак, прототип функции веб-сервиса всего лишь

Функция CmdExec(ParamStructure)
 
 СтруктураПараметров = ЗначениеИзСтрокиВнутр(ParamStructure);
 Результат = Новый Структура;
 Если СтруктураПараметров.Свойство("КодОбработки") Тогда
  Попытка
   Выполнить(СтруктураПараметров.КодОбработки);
  Исключение
   Результат.Вставить("Ошибка",ОписаниеОшибки());
  КонецПопытки;
 Иначе 
  Результат.Вставить("Ошибка","WS.ПСГ_Общий.CmdExec: Входная структура не содержит свойства КодОбработки.");
 КонецЕсли; 
 ВозвращаемоеЗначение = ЗначениеВСтрокуВнутр(Результат);
 
 Возврат ВозвращаемоеЗначение;
 
КонецФункции

В прилагаемой демонстрационной базе создан веб-сервис ПСГ_Общий, выставляющий приведенную функцию CmdExec. Для удобства использования применяется функция ПСГ_ОбработчикиВебСервисов.ВыполнитьКомандуЧерезВебСервис(Адрес,СтруктураПараметров,КодОбработки), принимающая на входе адрес веб-сервера, произвольную структуру параметров и код обработки данных, и возвращающая структуру, созданную функцией CmdExec на целевой базе.

Функция   ВыполнитьКомандуЧерезВебСервис(Адрес,СтруктураПараметров,КодОбработки) Экспорт
 
 СтрокаСоединения = Адрес + "/ws/wsGeneral.1cws?wsdl";
 
 wsAccount = wsAccount();
 Определения = Новый WSОпределения(СтрокаСоединения,wsAccount.Логин,wsAccount.Пароль);
 Прокси = Новый WSПрокси(Определения,"http://www.promstroi-group.ru/general","ПСГ_Общий","ПСГ_ОбщийSoap");
 Прокси.Пользователь = wsAccount.Логин;
 Прокси.Пароль = wsAccount.Пароль;
 
 СтруктураПараметров.Вставить("КодОбработки",КодОбработки);
 ДанныеСтрокой = Прокси.CmdExec(ЗначениеВСтрокуВнутр(СтруктураПараметров));
 Если ДанныеСтрокой = Неопределено Тогда
  ВызватьИсключение("Не удалось получить данные");
 КонецЕсли; 
 
 Данные = ЗначениеИзСтрокиВнутр(ДанныеСтрокой);
 Если Данные.Свойство("Ошибка") Тогда
  ВызватьИсключение(Данные.Ошибка);
 КонецЕсли; 
 
 Возврат Данные;
 
КонецФункции

Здесь wsAccount() возвращает данные для авторизации в виде структуры("Логин,Пароль").


Рассмотрим простейший "Hello, world" для нашего веб-сервиса, команду Ping, выясняющую, доступен ли сервис.

Функция Ping(Адрес) Экспорт
 
 СтруктураПараметров = Новый Структура;
 КодОбработки = "Результат.Вставить(""Статус"",""онлайн"");";
 Результат = ПСГ_ОбработчикиВебСервисов.ВыполнитьКомандуЧерезВебСервис(стр.АдресWS,СтруктураПараметров,КодОбработки);
 Попытка
  Возврат Результат.Статус;
 Исключение
  Возврат ОписаниеОшибки();
 КонецПопытки; 
 
КонецФункции

Демонстрационная база содержит три других примера: обработку Демо, считывающую произвольный справочник целиком, обработку Тиражирование объектов WS, позволяющую скопировать объект в выбранные базы с совпадающей по составу объектов (но не обязательно реквизитов) структурой.

Для установки демонстрационной базы нужно загрузить прилагаемую dt-выгрузку в новую пустую базу 1С и опубликовать ее на веб-сервере. Далее, в клиенте нужно зайти в справочник Базы данных, и прописать адрес базы в поле Веб-сервер у базы данных База 1, и выставить константу Эта база данных = База1. После этого демонстрационные обработки уже могут общаться с самой этой же базой через ее веб-сервис. Но, конечно, значительно интереснее создать еще одну копию базы, прописать ее в справочник Базы данных как База 2 и посмотреть общение между этими базами.

Не лишне предупредить, что знающий логин и пароль wsAccount(), обладает, фактически правами пользователя wsAccount().Логин в базе, и правами пользователя, под которым работает сервер 1С (или IUSR в файловом варианте), в операционной системе.

Скачать файлы

Наименование Файл Версия Размер
Демонстрационная база 11
.dt 89,17Kb
13.11.13
11
.dt 1.0.0.0 89,17Kb Скачать

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Ярослав Радкевич (WKBAPKA) 13.11.13 18:26
что то после пива не совсем вкурил... чуствую, что что-то полезное, но пока не могу понять, что...
2. Денис Лазарев (irreal) 13.11.13 18:45
Коротко говоря, отправляешь другой базе код, который нужно выполнить и его параметры структурой, и получаешь ответ структурой. Веб-сервис здесь лишь приспособленный к интернету транспорт. Практически вместо этого можно было бы применить COM-коннектор, но этот, прежде чем заработать, прокачает через инет весь cf. С веб-сервисом тоже прокачает, но не через инет, а между сервером 1с и веб-сервером, через инет пойдет полезный только объем.

Может показаться, что сложно писать код обработки в одной базе, который будет выполняться в другой. Но надо просто правильно распределять код - размещать в базе-сервере основную процедуру, а в базе-клиенте ее использрвать, типа

База - сервер:

Функция ОбщийМодуль.БольшаяИСложнаяТаблица(СтруктураПараметров) Экспорт
...МногаБукав
КонецФункции

База-клиент:

СтруктураПараметров = Новый Структура;
...Заполнение структуры
КодОбработки = "Результат.Вставить(""БольшаяТаблица"",ОбщийМодуль.БольшаяИСложнаяТаблица(СтруктураПараметров));";
Результат = ПСГ_ОбработчикиВебСервисов.ВыполнитьКомандуЧерезВебСервис(стр.АдресWS,СтруктураПараметров,КодОбработки);

// Вот большая таблица и получена:
БольшаяТаблица = Результат.БольшаяТаблица;

Конечно, следует учитывать, в каких терминах будет этот ответ. Если это разные конфигурации, то ссылки "оттуда" потеряют смысл, и нужно возвращать гуиды и наименования. То есть, работа не похожа на работу с объектной системой ком-коннектора. Но в случае, если имеется много одинаковых баз, да еще поддерживается сквозная НСИ, все вообще великолепно.
3. Ийон Тихий (cool.vlad4) 13.11.13 22:32
(2) irreal, конечно, замечательно, и идея достаточно простая и понятная, ну кто не думал, сделать Выполнить во внешней базе, и через внешнее соединение и даже через ВК (на этом сайте видел, 1CHServer как-то так называется). Вот только вопрос безопасности остался в сторонке. К сожалению в 1С нет безопасного Выполнить (или мне он неизвестен), т.е. правильно ли я понимаю, что работа таким образом через интернет это серьезная брешь в безопасности ИБ?
4. Денис Лазарев (irreal) 13.11.13 23:45
(3) Снижение до уровня защиты в авторизации 1С - безусловно. К тому же, нужно извратиться, чтобы скрыть получение логина и пароля в коде, если к коду имеют доступ, например, аутсорсеры.
С другой стороны, выставить в открытый интернет базу данных я не решился бы и без этого. Интернет интернетом, но в рамках приличия - VNP. На предмет наличия злоумышленника, перехватывающего пакеты внутри сети - да, место слабое.

К слову сказать, мне пока не удалось заставить клиент веб-сервиса 1С авторизоваться по аутентификации ОС, поэтому в коде есть это самое wsAccount() - действие, чью имплементацию я намеренно вынес в отдельную функцию. Если бы удалось ввести виндовую авторизацию, дело обстояло бы гораздо лучше.

Один из способов эмуляции такого поведения на стороне кода в клиенте - вынести конфиденциальную информацию в базу SQL, закрыть доступ к таблицам и выставить только интерфейсную функцию, которая по авторизации ОС решит, что и давать ли вообще. Но уязвимость к перехвату внутри сети остается.
cool.vlad4; +1 Ответить
5. Дмитрий Шерстобитов (DitriX) 14.11.13 12:17
(3) в платформе 8.3 появился Безопасный режим. Т.е. вы работать можете только в среде 1С, и вам не доступно внешнее окружение.
Однако, Выполнить, это не только брешь в безопасности, но и возможность получить кучу проблем. Хотели очистить регистр штрихкдов в 2 базах, и случайно очистили везде.
Т.е. Выполнить - не панацея. Это все равно что сидеть на сервере под учеткой админа, когда для ваших нужд вполне хватает обычного пользователя. А если что то надо админское, то вы запускаете программу от имени админа.

(0)Короче - это вариант не новый, его уже в разных видах представляли тут.
Вот если вы попробуете пройтись по всем аналогичным темам и решить все проблемы там описанные, ответить на все вопросы, вот тогда будет гут.
6. Антон Стеклов (asved.ru) 20.11.13 09:56
Зачем применять строковое преобразование, если можно использовать прекрасно сериализующееся ХранилищеЗначения?
7. Денис Лазарев (irreal) 20.11.13 17:39
(6) asved.ru, логично, можно и так.
8. Артур Аюханов (artbear) 21.11.13 15:08
Очень опасная схема :(
Кто угодно может выполнить код 1С в любой базе :(
9. Денис Лазарев (irreal) 21.11.13 21:44
(8) artbear, Для этого "кому угодно" нужно, как минимум, знать логин и пароль веб-сервиса. Выполнение внешних обработок ползователями у нас запрещено, так что здесь не прорвешься, даже зная API. В конце концов, Выполнить() используется, например, в УниверсальныйОбменДаннымиXML. Можно, подсунуть вредоносные правила пользователю этой обработки, если она вдруг ему доступна.