Когда хотим знать IP клиента...

03.07.20

Интеграция - WEB-интеграция

В процессе разработки web приложения на 1С, и это не шутка))), а пожелание заказчика, возникла ситуации когда понадобилось знать, с какого IP подключался клиент.

Не судите строго, пишу первый раз. Хотя и были попытки до этого, но так не разу не опубликовал.

И так есть самописная конфигурация на Платформе 8.3 с кусками БСП, в ней реализован некий web сервис для клиентов компании.

В web сервисе есть графический интерфейс для работы из браузера и rest api.

Была поставлена задача определять IP адрес клиента в независимости от того как он подключился к сервису.

Помогли в решении эти посты:

//infostart.ru/public/1159393/

//infostart.ru/public/1157609/

//infostart.ru/public/338126/

И так у нас два варианта подключения. Начнем пожалуй с самого простого и быстрого получить IP при подключении через REST API.

Клиент получает данные через HTTP запросы, обращается к 1С базе через web сервер Apache.

Apache знает IP клиента, и мы можем поместить это адрес в некую переменную.

Для этого нам нужно:

в файле конфигурации Apache раскомментировать строки

#LoadModule headers_module modules/mod_headers.so
#LoadModule ssl_module modules/mod_ssl.so

добавить строки

# Проброс ip адреса клиента для http-сервисов 1С в заголовке client_ip_addr
RequestHeader append client_ip_addr "%{REMOTE_ADDR}s"

во все вызовы HTTP методов в базе 1С внедрить код, получающий ip клиента от Apache. В нашем случаи мы делаем так. Главное это как видите получения IP изи Заголовка http запроса.

Попытка
     ipКлиентаОпределен = ПараметрыСеанса.IpКлиента;
Исключение
     ПараметрыСеанса.IpКлиента = Запрос.Заголовки.Получить("client_ip_addr");
КонецПопытки;

И мы сохраняем в параметры сеанса, так как пока сеанс жив то нет смысла обновлять IP.

С эти всё оказалось просто. Но есть второй случай когда клиент не использует REST API, а заходит через web клиент.

Как узнать внешний IP клиента?

Мы решили так, пусть клиент сам нам скажет свой IP.

Но просить его писать это в поле ещё и смотреть в интернете было бы странно.

Значить это должно сделать за него 1С.

Решение приведенное ниже не является красивым, и работает не во всех 100% случаев (об этом ниже).

Клиент 1С сам по себе не имеет информации о настройках сетевой карты машины, на которой он исполняется, и даже если получит эту информацию - она может ничего не сказать о внешнем ip-адресе.
Очевидным решением является "спросить" у общедоступных сервисов наш ip-адрес с использованием HTTP-подключения например к ресурсу https://json.geoiplookup.io/api.
Но это невозможно сделать для web-клиента, т.к. методы работы с HTTP недоступны на web-клиенте

Значит нужно какое-то другое решение, и таким решением будет отображение поля HTML документа с js, а из js можно вызвать get https://json.geoiplookup.io/api.
Нюанс: просто создать HTML-документ недостаточно: js внутри него не отработает, также просто создать и не отображать форму не выйдет - js в поле HTTP-документа запускается только при отображении, в этом и состоит "некрасивость" решения - пользователю придется лицезреть запуск этой формы.

Если сделать пару допущений, то станет ясно, что все не так плохо:

Допущение №1 - скорость выполнения обработки достаточно высокая, чтобы пользователь ее не заметил В толстом и тонком клиенте выполнение такой обработки будет почти мгновенным и пользователем (вероятно) останется незамеченным. Что же до web-клиента? там все медленно!

Допущение №2 - такую обработку имеет смысл запускать при старте приложения и в этот момент можно ее чем-нибудь прикрыть Можно запустить свое лого на web-страничке во время загрузки web-клиента и отображения окна обработки.

 

  • Первое что понадобится - место где мы будем хранить полученную информацию, в нашем случае это параметр сеанса IpКлиента.
  • Второе - сама обработка
    Создаем обработку, и форму в ней (на самом деле подойдет любой вид форм).
    На форму добавляем строковый реквизит "HTMLДокумент", в элементах задаем ему вид Поле HTML документа
    и целочисленный реквизит "ПопытокПолученияIPСделано", он будет хранить информацию о том как долго длится попытка получения ip-адреса.
    Код модуля формы:

 

&НаКлиенте
Процедура ПриОткрытии(Отказ)
	Попытка
		// синхронный запрос GET
		HTMLДокумент = "
		|<!DOCTYPE html>
		|<html>
		|	<head>
		|		<meta charset='UTF-8'>
		|		<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js' type='text/javascript'></script>
		|	</head>
		|	<body></body>
		|	<script>
		|		function httpGet(theUrl) {
		|			var xmlHttp = new XMLHttpRequest();
		|			xmlHttp.open( 'GET', theUrl, false ); // false for synchronous request
		|			xmlHttp.send( null );
		|			return xmlHttp.responseText;
		|		}
		|		
		|		getIp = function() {
		|			try {
		|				responseText = httpGet('https://api.ipify.org/?format=json');
		|				JSONresponce = JSON.parse(responseText);
		|				$('body').text(JSONresponce.ip);
		|			} catch(ex) {
		|				try {
		|					responseText = httpGet('https://ipinfo.io/json');
		|					JSONresponce = JSON.parse(responseText);
		|					$('body').text(JSONresponce.ip);
		|				} catch(ex) {
		|					try {
		|						responseText = httpGet('https://www.cloudflare.com/cdn-cgi/trace?format=json');
		|						JSONresponce = JSON.parse(responseText);
		|						$('body').text(JSONresponce.ip);
		|					} catch(ex) {
		|						$('body').text('Блокирован');
		|					}
		|				}
		|			}
		|		};
		|		
		|		$(document).ready(function() {
		|			getIp();
		|		});
		|	</script>
		|</html>";
	Исключение
	КонецПопытки;
	
	// синхронное получение получает пустой ip т.к. js исполняется в отдельном потоке
	// асинхронное получение/ожидание
	ПодключитьОбработчикОжидания("ПопытатьсяПолучитьСодержаниеHTML", 1, Ложь);
КонецПроцедуры


&НаКлиенте
Процедура ПопытатьсяПолучитьСодержаниеHTML()
	Страница = Элементы.HTMLДокумент.Документ;
	Попытка
		ПопытокПолученияIPСделано = ПопытокПолученияIPСделано + 1;
		Если ЗначениеЗаполнено(Страница.body.innerHTML) Тогда
			ip = Страница.body.innerHTML;
			
			ОтключитьОбработчикОжидания("ПопытатьсяПолучитьСодержаниеHTML");
			СохранитьКлиентскийIPВПараметрыСеанса(ip);
			ЭтаФорма.Закрыть();
		КонецЕсли;
	Исключение
	КонецПопытки;
	
	// если попытки получения неудачны - закончить
	Если ПопытокПолученияIPСделано > 3 Тогда
		ОтключитьОбработчикОжидания("ПопытатьсяПолучитьСодержаниеHTML");
		ЭтаФорма.Закрыть();
	КонецЕсли;
КонецПроцедуры

&НаСервере
Процедура СохранитьКлиентскийIPВПараметрыСеанса(ip)
	ПараметрыСеанса.IpКлиента = ip;
КонецПроцедуры

 

ПриОткрытии() устанавливается тело HTML-документа с js, в js происходит попытка получения ip-адреса из одного из трех сервисов последовательно.
Если в браузере используется блокировщик - адреса ресурсов могут быть недоступны, в связи с чем получение ip-адреса ни из одного из ресурсов может не произойти, необходимо будет искать сервис, не находящийся в базе блокировщиков.
При успехе исполнения ip-адрес записывается в тело документа.

Каждую секунду в течение 3 секунд происходит асинхронная попытка получения текста HTML-документа (процедура ПопытатьсяПолучитьСодержаниеHTML()), в случае успеха происходит запись полученного значения в параметр сеанса.
После успеха или неуспеха форма закрывается.

  • Третье - время ее запуска. В нашем случае это модуль приложения, ПриНачалеРаботыСистемы().
    При начале работы системы запускаем обработку, активируем начальную страницу в попытке скрыть процесс работы обработки
    Процедура ПриНачалеРаботыСистемы()
    	
    	// СтандартныеПодсистемы
    	СтандартныеПодсистемыКлиент.ПриНачалеРаботыСистемы();
    	// Конец СтандартныеПодсистемы
    	
    	// определение ip-адреса клиента
    	ОткрытьФорму("Обработка.УстановкаIpКлиентаВПараметрыСеанса.Форма.Форма");
    	// активизировать главное окно
    	ОкнаПриложения = ПолучитьОкна();
    	Для Каждого Окно Из ОкнаПриложения Цикл
    		Если Окно.НачальнаяСтраница = Истина Тогда
    			Окно.Активизировать();
    		КонецЕсли;
    	КонецЦикла;		
    КонецПроцедуры

Вот и всё. Теперь мы почти всегда знаем, с какого IP к нам подключался клиент.

Надеюсь, в статье всё понятно. Ждём комментариев.

обработка web IP API Apache REST 1C HTTP сервис клиент статистика

См. также

Интеграция Альфа Авто 5 / Альфа Авто 6 и AUTOCRM / Инфотек

Сайты и интернет-магазины WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме.

36000 руб.

03.08.2020    15747    10    17    

11

Интеграция 1С — Битрикс24. Обмен задачами

Сайты и интернет-магазины Интеграция WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 Управленческий учет Платные (руб)

Интеграция 1С и Битрикс24. Разработка имеет двухстороннюю синхронизацию 1С и Битрикс24 задачами. Решение позволяет создавать пользователя в 1С из Битрикс24 и наоборот. Данная разработка технически подходит под все основные конфигурации линейки продуктов 1С:Предприятие 8.3 (8.3.18.1289). При приобретении предоставляется 1 месяц бесплатных обновлений разработки. Доступна демо-версия продукта с подключением Вашего Битрикс24

5040 руб.

04.05.2021    17550    6    15    

13

Интеграция с сервисом vetmanager

WEB-интеграция Платформа 1С v8.3 Бухгалтерский учет 1С:Бухгалтерия 3.0 Бытовые услуги, сервис Платные (руб)

Внешняя обработка разрабатывалась для загрузки документов из Ветменеджер в 1С: Бухгалтерия 3.0

12000 руб.

02.02.2021    16360    42    49    

23

[Расширение] БОР-Навигатор.Культура

Зарплата Бюджетный учет WEB-интеграция Обмен с ГосИС Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бюджетный учет Платные (руб)

Расширение конфигурации, включающее в себя объекты, необходимые для подготовки и сдачи отчета "Штатная численность" системы "БОР-Навигатор.Культура" в программе "1С:Зарплата и кадры государственного учреждения", редакция 3.1.

8400 руб.

01.02.2019    25741    9    0    

7

Заполнение по ИНН или наименованию реквизитов контрагента по данным сайта ФНС

Обмен с ГосИС WEB-интеграция Платформа 1С v8.3 Управляемые формы 1С:Комплексная автоматизация 1.х 1С:Бухгалтерия 2.0 1С:Управление торговлей 10 1С:Управление производственным предприятием 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия государственного учреждения 1С:Документооборот 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Платные (руб)

Обработка является альтернативой механизму, разработанному фирмой 1С и заполняющему реквизиты контрагента по ИНН или наименованию. Не требуется действующей подписки ИТС. Вызывается как внешняя дополнительная обработка, т.е. используется, непосредственно, из карточки контрагента. Заполнение по ИНН или наименованию реквизитов контрагента по данным сайта ФНС (egrul.nalog.ru) для БП 2.0, БП 3.0, БГУ 1.0, БГУ 2.0, УТ 10.3, УТ 11.x, КА 1.1, КА 2.x, УПП 1.x, ERP 2.x, УНФ 1.5, УНФ 1.6, УНФ 3.0, ДО 2.1

2400 руб.

28.04.2016    88580    160    215    

318
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. kolabaister 3 03.07.20 16:08 Сейчас в теме
Когда я столкнулся с подобной задачей, решить ее без костыля не удалось. Там делалось что то вроде get api, соответственно ничего выполнить на стороне клиента нельзя.
В итоге был сделан прокси-сервис, который берет на себя задачи контроля доступа, блокировки и вот этого вот всего. А сервис в свою очередь обращается к базе, и соединение уже идет как доверенное. Если бы в базу потребовалось передать ip обратившегося, я бы просто добавил параметр к запросу, модифицировав его сервисом.

К вопросу про блокировщики рекламы - такая проблемка тоже была в свое время, в другом проекте. Был поднят в домене сторонний мини-сервис, единственной задачей которого было отдавать ip адрес обратившегося в зашифрованном виде. Приложение расшифровывало его и получало гарантированно доверенный
4. IMihalev 9 06.07.20 05:06 Сейчас в теме
(1) Хорошая идея про собственный Whois надо подумать над этим, но придётся его стратифицировать, если блокировку антивирус делает.
6. kolabaister 3 06.07.20 08:26 Сейчас в теме
(4)Ну, не совсем. Если сервис находится на домене компании, то если антивирус его заблокирует это будет меньшая из проблем.
7. IMihalev 9 07.07.20 02:48 Сейчас в теме
(6) Ну пока у нас 100% идентификация клиентов. Если начнутся проблемы, то мы попробуем реализовать свой Whois. Большое спасибо за идею.
2. serg33rus 21 03.07.20 19:07 Сейчас в теме
Я может что-то путаю, но насколько я помню, в 17 платформе это штатная возможность.
Точно
"Реализована возможность определения IP-адреса компьютера, который начал сеанс работы с информационной базой. IP-адрес может быть определен не всегда и не для всех режимов работы.
Реализовано свойство IPАдресКлиента для объектов АдминистрированиеСеанс и СеансИнформационнойБазы.


Источник: https://dl04.1c.ru/content/Platform/8_3_17_1032/1cv8upd_8_3_17_1032.htm#6485437a-fb18-11e9-8371-0050569f678a"
3. kolabaister 3 03.07.20 22:16 Сейчас в теме
(2)Да, в апреле 20 года появилось.
5. IMihalev 9 06.07.20 05:08 Сейчас в теме
(2) Нам не нужен ip компьютера клиента, нам нужен внешний(реальный) ip в интернете. А платформа локальный выдаёт.
8. 7OH 69 07.07.20 15:06 Сейчас в теме
(5) а если отдел через роутер работает, как выходите из ситуации ?
9. IMihalev 9 19.08.20 03:02 Сейчас в теме
(8) Что значит через роутер? Клиент подключается к нам через интернет, в любом случаи мы видим его внешний IP даже если он динамический.
10. DERL 26.08.20 05:26 Сейчас в теме
https://json.geoiplookup.io/api врет и не краснеет
я вот этим пользуюсь https://ipapi.co/json/
user1430606; +1 Ответить
14. user1430606 17.09.21 09:33 Сейчас в теме
(10) Спасибо не плохая идея.
15. user1430606 17.09.21 09:36 Сейчас в теме
(10)
Но в статье ошибка, если вы видите код то там как раз https://ipapi.co/json/
11. zergev 15.09.21 14:33 Сейчас в теме
Была похожая задача. Вытянул из ПолучитьТекущийСеансИнформационнойБазы() в общем модуле с галочкой «Сервер», процедуру которого вызвал из модуля приложения из процедуры «ПередНачаломРаботыСистемы()». Мне нужно было лишь в ЖурналРегистрации записать ip-адрес клиента.
12. alf2006x 25 16.09.21 18:54 Сейчас в теме
(11) А можно чуть подробнее ? Кусочек примера - идеальный вариант.
13. alf2006x 25 16.09.21 18:59 Сейчас в теме
16. enp2003@list.ru 14.06.23 16:33 Сейчас в теме
HTTP запрос-Заголовки- X-Forwarded-For
17. user1600314 19.01.24 18:00 Сейчас в теме
Соединение = Новый HTTPСоединение("api.ipify.org");
	Запрос = Новый HTTPЗапрос("/?format=json");
	Ответ = Соединение.Получить(Запрос);
	ТелоОтвета = (Ответ.ПолучитьТелоКакСтроку());
18. user1600314 19.01.24 18:01 Сейчас в теме
дабы не городить поле хтмл документа
Оставьте свое сообщение