Как получить IP адрес пользователя в тонком/толстом и веб-клиенте

Администрирование - Защита, права, пароли

Пример использования связки JavaScript и 1С для получения локального IP адреса пользователя.

В крупных компаниях вопрос информационной безопасности стоит крайне остро.  Особенно если используется разделение данных и какая-нибудь учетка может "гулять" из рук в руки довольно часто. Также невозможно нормально проанализировать, из каких мест работает специалист. Журнал регистрации 1С всем хорош, да только не при работе в веб-клинете.  И для того чтобы мониторить весь этот процесс, важно понимать с какого компьютера или IP работает пользователь. Вся сложность заключается в том, что платформа веб-клиента в 1С существенно ограничена и запуск средств ActiveX которыми можно удобно пользоваться зачастую отлючен во всех браузерах. В поисках решения проблемы наткнулся на одно из описаний с возможностью запуска кода JavaScript в поле HTML документа формы. Во всех популярных браузерах последних поколений давно включена технология WebRTC  которая и поможет нам получить желаемые данные. WebRTC поддерживается в Chromium и браузеров на его основе с 17 версии, Opera с 12 версии и Firefox с 18 версии (без флага — с 22-й) а также в Microsoft Edge. Для других браузеров можно использовать расширение webrtc4all.

Сразу оговорюсь, что решение довольно костыльное, но по другому не получилось, возможно, надеюсь, кто-то сделает лучше, пока так. Сильно не бейте! :)

1. Пример кода JavaScript для получения локального адреса:

function findIP(onNewIP) { //  onNewIp - your listener function for new IPs
  var myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; //compatibility for firefox and chrome
  var pc = new myPeerConnection({iceServers: []}),
    noop = function() {},
    localIPs = {},
    ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g,
    key;

  function ipIterate(ip) {
    if (!localIPs[ip]) onNewIP(ip);
    localIPs[ip] = true;
  }
  pc.createDataChannel(""); //create a bogus data channel
  pc.createOffer(function(sdp) {
    sdp.sdp.split('\n').forEach(function(line) {
      if (line.indexOf('candidate') < 0) return;
      line.match(ipRegex).forEach(ipIterate);
    });
    pc.setLocalDescription(sdp, noop, noop);
  }, noop); // create offer and set local description
  pc.onicecandidate = function(ice) { //listen for candidate events
    if (!ice || !ice.candidate || !ice.candidate.candidate || !ice.candidate.candidate.match(ipRegex)) return;
    ice.candidate.candidate.match(ipRegex).forEach(ipIterate);
  };
}

var ul = document.createElement('ul');
ul.textContent = 'Your IPs are: '
document.body.appendChild(ul);

function addIP(ip) {
  console.log('got ip: ', ip);
  var li = document.createElement('li');
  li.textContent = ip;
  ul.appendChild(li);
}

function getLocalIp(){
	findIP(addIP);
}

В 1С мы должны вызвать фунцию getLocalIp(), для этого создадим форму, на ней поле HTML документа с данными в строчном реквизите "Док". Для удобства создадим макет с типом "Текстовый документ", там будет наш HTML с кодом JavaScript. При создании формы передадим текст макета в реквизит "Док".

ОбработкаОбъект = РеквизитФормыВЗначение("Объект");	
Док = ОбработкаОбъект.ПолучитьМакет("МакетДок").ПолучитьТекст();

Также привяжем к событию "ДокументСформирован" определение необходимых переменных, для их последующего быстрого вызова.

#Если  ВебКлиент Тогда
	// Исключение обработки дубля события "ДокументСформирован"
	Если НЕ БраузерЗагрузкаОбработана Тогда
		БраузерЗагрузкаОбработана = Истина;
		// Сохранение элементов document и window в переменных формы,
		// для последующего быстрого доступа к элементам и функциям.
		ДокументБраузера = Элемент.Документ;
		ОкноБраузера 	= ДокументБраузера.parentWindow;
		Если ОкноБраузера = Неопределено Тогда
			ОкноБраузера = ДокументБраузера.defaultView;	
		КонецЕсли;
		ОкноБраузера.externalForm = ЭтаФорма;
	КонецЕсли;
#КонецЕсли

Создадим команду "ПолучитьИП" и поместим на форму кнопку, со следующим кодом:

#Если ВебКлиент Тогда
	ОперацияДляБраузера();
#Иначе
	ОперацияДляКлиента();
#КонецЕсли

Функция для для браузера имеет следующий вид:

&НаКлиенте
Процедура ОперацияДляБраузера()
	
	Попытка
		// Передаем функции JavaScript строку ""
		ОкноБраузера.getLocalIp("");
		ПоолучениеИПсоСтраницы();
	Исключение
		Ош = ОписаниеОшибки();
		Сообщить(Ош);
	КонецПопытки;
	
КонецПроцедуры

"ОкноБраузера.getLocalIp("");" - так мы вызвали фунцию JavaScript из нашей формы. Стоит также заметить, что этот метод асинхронный и на его выполнение потребуется какое-то время. 

 Затем спарсим полученный результат со страницы HTML документа таким образом:

&НаКлиенте
Процедура ПоолучениеИПсоСтраницы()
	
	Неудача = Ложь;
	Попытка
		ЛокальныйIPСтрока = ОкноБраузера.window.ul.innerHTML;
		МасСтр = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(ЛокальныйIPСтрока, "<li>");
		НомерСимвола = Найти(МасСтр[1], "<");
		ЛокальныйIP = Лев(МасСтр[1], НомерСимвола - 1);
	Исключение
		ЛокальныйIP = ОписаниеОшибки();
		Неудача = Истина;
	КонецПопытки;
	
	Если Неудача Тогда
		ИП = "Не удалось получить локальный IP!";
	Иначе
		ИП = СтрЗаменить(ЛокальныйIP, """", "");
	КонецЕсли;
	
КонецПроцедуры

Вверху можно увидеть, что при помощи .window.ul.innerHTML мы обратились к переменной "li", которую создали выполняя код JavaScript : "var li = document.createElement('li');" а затем поместили в него полученные данные: " li.textContent = ip;".

Можно попробовать получать значение и не помещая его на страницу, а при помощи JSon обьекта. Подробнее тут.

Для получения локального IP из клиента (правда если речь идет про ОС Windows) я сделал так:

МойИП = "";
strComputer = ".";
SWBemlocator = Новый COMОбъект("WbemScripting.SWbemLocator");
objWMIService = SWBemlocator.ConnectServer(strComputer, "root\CIMV2");
IPConfigSet = objWMIService.ExecQuery("Select IPAddress from Win32_NetworkAdapterConfiguration where ipenabled = true");
	
Для Каждого Конфигурация Из IPConfigSet Цикл
	Для Каждого СтрПараметр Из Конфигурация.IPAddress Цикл
		Если ПроверимНаИП4(СтрПараметр) Тогда
			МойИП = СтрПараметр;
		КонецЕсли;
	КонецЦикла;
КонецЦикла;
	
Док = ПолучитьДляКлиентаТекстХТМЛ(МойИП);

а затем поместим полученный IP в HTML документ:

&НаКлиенте
Функция ПолучитьДляКлиентаТекстХТМЛ(Стр)
	
	Текст = "<html>
	|<head>
	|	<META content=text/html;charset=utf-8 http-equiv=content-type></META>
	|<meta http-equiv=""X-UA-Compatible"" content=""IE=8"" />
	|</head>
	|<body>
	| Your IP is: " + Стр + " 
	|</body>
	|</html>";
	
	Возврат Текст;
	
КонецФункции

Вот и все, надеюсь, это кому-то пригодится. 

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

Наименование Файл Версия Размер
ПолучениеПользователяИП.epf
.epf 10,09Kb
20.02.17
17
.epf 1.01 10,09Kb 17 Скачать

См. также

Комментарии
1. Матти Нюкянен (Nykyanen) 217 22.09.17 19:01 Сейчас в теме
При нажатии на кнопку "Получить IP" выдает ошибку: Error calling context method (getLocalIp): Object doesn't support property or method 'createDataChannel'
Работа через вебклиента. Версия 1С 8.3.9.1818, режим совместимости Версия 8.3.6, веб-сервер на IIS 8.5.
Браузер: Microsoft Edge 40.15063.0.0 / Microsoft EdgeHTML 15.15063
Прикрепленные файлы:
2. Матти Нюкянен (Nykyanen) 217 22.09.17 19:06 Сейчас в теме
При запуске через тонкий клиент с подключением через веб-ссылку выдает локальный IP клиента, а не внешний.
Что то типа 192.168.x.x
3. Александр Монагаров (promogiantworm) 58 26.09.17 15:08 Сейчас в теме
Привет, видимо браузер не поддерживает или намеренно отключен WebRTC - тут увы и ах, ничего не сделаешь. Но у меня сейчас эта штука работает на предприятии и в 98% определяет, соответсвенно никто не пользуется Microsoft Edge (ну зачем этот хлам юзать, если есть куча нормальных браузеров?). IP именно внутренний, такова была цель. Внешний проще получить - можно через web-сервис например или как фантазия позволит.
4. Андрей Золотарёв (belpoprygun) 26.09.17 15:21 Сейчас в теме
Можно реализовать доступ к внешнему сервису, который по запросу извне отдаёт реальный IP-адрес, и его использует клиент.
5. andrey P (andrey314) 10 26.09.17 16:01 Сейчас в теме
Есть ли возможность получить ір-адрес или мас-адрес в мобильном приложении?
6. Александр Монагаров (promogiantworm) 58 26.09.17 17:47 Сейчас в теме
(5)Не было опыта работы с моб. приложением. Может другие подскажут.
Оставьте свое сообщение