В процессе разработки и администрирования систем на базе 1С часто возникает необходимость идентификации рабочего места пользователя не только по имени компьютера, но и по его сетевому адресу — для этой задачи есть администрирование рабочих мест и кассового оборудования. Это может потребоваться для ведения расширенных логов безопасности, привязки лицензий к конкретным рабочим станциям или проектирования защищенной IT-инфраструктуры предприятии. В этой статье мы подробно разберем несколько эффективных способов получения IP-адреса клиента, проанализируем их плюсы и минусы, а также изучим примеры кода для реализации этой задачи.
Первый и наиболее "чистый" с точки зрения архитектуры 1С способ — это обращение к списку активных соединений информационной базы. Платформа 1С:Предприятие предоставляет механизмы для программного получения информации о текущих сеансах. Давайте проанализируем ситуацию: нам нужно найти текущее соединение и извлечь из него сетевой адрес.
Рассмотрим алгоритм действий. Сначала мы определим уникальный идентификатор текущего сеанса, затем получим список всех соединений и найдем в нем наше. Важно помнить, что метод ПолучитьСоединенияИнформационнойБазы() требует наличия определенных прав доступа, поэтому этот код лучше выполнять в привилегированном модуле или под правами администратора. Для этой задачи есть обработка принудительного завершения сеансов пользователей 1С.
Разберем по шагам реализацию этой логики в коде:
Функция ПолучитьIPАдресТекущегоСеанса() Экспорт
// Получаем номер текущего сеанса
НомерСеанса = НомерСеансаИнформационнойБазы();
// Получаем массив всех активных соединений
Соединения = ПолучитьСоединенияИнформационнойБазы();
Для Каждого ТекущееСоединение Из Соединения Цикл
// Сравниваем номер сеанса в массиве с нашим текущим номером
Если ТекущееСоединение.НомерСеанса = НомерСеанса Тогда
// Свойство ИмяКомпьютера часто содержит IP в сетевом формате
Возврат ТекущееСоединение.ИмяКомпьютера;
КонецЕсли;
КонецЦикла;
Возврат "";
КонецФункции
Важный момент: в клиент-серверном варианте работы свойство ИмяКомпьютера объекта СоединениеИнформационнойБазы часто возвращает именно имя хоста, а не прямой IP-адрес. В таких случаях нам потребуются альтернативные инструменты, предоставляемые операционной системой.
Если стандартных средств платформы недостаточно, мы можем обратиться к возможностям операционной системы через COM-объекты. Один из самых мощных инструментов в ОС Windows — это WMI. Мы рассмотрим подробнее, как с помощью SWbemLocator получить список всех сетевых адаптеров. Стоит отметить, что вы также можете использовать COM-объекты на Python для 1С, чтобы расширить стандартный функционал получения системных данных.
Этот метод работает на стороне клиента (Windows) и позволяет получить детальную информацию обо всех сетевых интерфейсах, включая виртуальные и VPN-соединения. Посмотрим на пример кода, который выполняет запрос к системному репозиторию:
Функция ПолучитьIPЧерезWMI() Экспорт
Попытка
// Создаем локатор для доступа к WMI
Локатор = Новый COMОбъект("WbemScripting.SWbemLocator");
// Подключаемся к локальному компьютеру в пространство имен CIMV2
СервисWMI = Локатор.ConnectServer(".", "root\cimv2");
// Формируем запрос для получения настроек сетевых адаптеров
// Нас интересуют только те, у которых включен IP
Запрос = "SELECT IPAddress FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True";
РезультатЗапроса = СервисWMI.ExecQuery(Запрос);
Для Каждого Объект Из РезультатЗапроса Цикл
// IPAddress возвращается как массив строк
Если Объект.IPAddress <> Неопределено Тогда
Для Каждого ТекущийIP Из Объект.IPAddress Цикл
// Игнорируем IPv6 (содержат двоеточия), если нужен только IPv4
Если Найти(ТекущийIP, ":") = 0 Тогда
Возврат ТекущийIP;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Исключение
Возврат "Ошибка доступа к WMI: " + ОписаниеОшибки();
КонецПопытки;
Возврат "Не найден";
КонецФункции
При использовании этого метода стоит учитывать, что он предназначен для работы под управлением Windows. Если вы используете тонкий клиент под Linux или macOS, данный код не сработает, и следует предусмотреть проверку типа операционной системы.
Существует еще один "классический" подход, который часто обсуждается на форумах — программный запуск утилиты ipconfig и чтение результата её работы. Этот метод хорош тем, что он не требует сложной настройки COM-объектов, но требует корректной обработки текстовых данных. Разберем, как реализовать это через временные файлы.
Алгоритм действий следующий:
cmd /c ipconfig > [путь_к_файлу] в скрытом режиме.Посмотрим на пример реализации:
Функция ПолучитьIPИзКоманднойСтроки()
ИмяФайлаРезультата = ПолучитьИмяВременногоФайла("txt");
// Команда для выполнения
Команда = "cmd /c ipconfig > """ + ИмяФайлаРезультата + """";
// Запускаем приложение и ждем завершения (параметр Истина)
ЗапуститьПриложение(Команда, , Истина);
ЧтениеТекста = Новый ЧтениеТекста(ИмяФайлаРезультата, КодировкаТекста.OEM);
ТекстРезультата = ЧтениеТекста.Прочитать();
ЧтениеТекста.Закрыть();
// Удаляем временный файл
УдалитьФайлы(ИмяФайлаРезультата);
// Простейший поиск строки с IP
Позиция = Найти(ТекстРезультата, "IPv4");
Если Позиция > 0 Тогда
// Здесь можно добавить более точный парсинг строки
Возврат "IP найден в выводе команды";
КонецЕсли;
Возврат "Не определено";
КонецФункции
Проанализируем ситуацию: основной недостаток этого метода — зависимость от языка операционной системы. В качестве альтернативы для быстрого получения адреса, с которым компьютер виден в сети, можно использовать готовый MyIP сервис на Python.
Если ваша база опубликована на веб-сервере и пользователи работают через браузер, ситуация меняется. Код, запущенный в веб-клиенте, не имеет прямого доступа к аппаратным ресурсам компьютера. В этом случае выясним причину невозможности получения локального IP: браузер скрывает эти данные. Для решения проблем идентификации пользователей в таких условиях отлично подходит расширение для Chrome по передаче GUID клиента.
Для решения этой задачи в веб-клиенте обычно используются следующие подходы:
X-Forwarded-For), если используется прокси-сервер или балансировщик — для этого подойдёт сбор и анализ логов HTTP-запросов для 1С.Пример обращения к внешнему сервису для определения внешнего IP-адреса:
&НаКлиенте
Функция ОпределитьВнешнийIP()
HTTPСоединение = Новый HTTPСоединение("api.ipify.org");
Запрос = Новый HTTPЗапрос("/");
Ответ = HTTPСоединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда
Возврат Ответ.ПолучитьТелоКакСтроку();
КонецЕсли;
Возврат "";
КонецФункции
Подводя итог нашему исследованию, можно сделать следующие выводы по выбору метода:
ПолучитьСоединенияИнформационнойБазы) — идеален для административных задач внутри системы, когда важна привязка именно к сессии 1С.При реализации любого из этих методов мы рекомендуем всегда использовать блоки Попытка...Исключение, так как работа с внешними компонентами всегда сопряжена с риском возникновения ошибок. Таким образом, мы выяснили, что задача получения IP-адреса в 1С 8.3 имеет множество решений в зависимости от контекста выполнения кода.