Методы определения местоположения пользователя

от автора

Предисловие

Всем, кто когда-либо занимался написанием систем авторизации/регистрации пользователей, наверняка приходилось задаваться вопросом: «А как узнать о пользователе больше информации?». Для чего это нужно? В большинстве случаев, для идентификации именно этого пользователя. Иногда — для предоставления каких-либо дополнительных возможностей и информации, в зависимости от различных социальных параметров, или, быть может, местополжения пользователя или региона проживания. Иногда, например, для проведения какого-либо скоринга. В этой статье речь пойдёт об определении географического положения пользователя.

Эффективные методы определения

Можно придумать массу методов получения георгафического положения пользователя интернета. И все эти методы будут обладать своим набором плюсов и минусов, будут более или менее эффективны, в зависимости от применения. Сейчас я опишу только те методы, которыми на данный момент пользуется проект, в котором я учавствую, т.е. те, которые я непосредственно использую. За время существования проекта по ним уже собралось достаточно статистики, из которой можно сделать некоторые выводы.

1. Данные из соц. сетей

На сегодняшний день крайне популярным стало использовать для авторизации (или в качестве дополнительной информации) аккаунты всевозможных социальных сетей и блогов, что позволяет использовать данные из них. Авторизовав пользователя таким образом, можно получить достаточно много информации о нём. Правда вот о достоверности её говорить не приходится, ведь многие указывают в соц. сетях не «действительное», а «желаемое», либо вообще первое, что пришло в голову. Отсеять подобные вещи обычно и есть основная задача для разработчика. Для этого необходимо получить информацию обо всех друзьях пользователя и сверить общие данные. Можно, например, найти наиболее часто встречаемое место проживания у коллег/однокурсников/одноклассников/друзей пользователя (в синей соц. сети, например, это делать очень удобно), и, на основе этих данных, выяснить настоящий регион, область, город и даже район города, где живёт/работает/учится пользователь.
Также, в некоторых соц. сетях, доступно получение непосредственных координат пользователя, если он онлайн. Точность этих данных, в некоторых случаях, оставляет желать лучшего, но, как минимум, район города, где находится пользователь, определить можно достаточно достоверно.

Плюсы:

  • Относительно высокая точность, при использовании моделей скоринга на основе данных друзей
  • У большинства пользователей есть аккаунты в соц. сетях
  • Можно проверить полученные данные на достоверность, используя данные друзей

Минусы:

  • Сложность реализации, т.к. необходимо изучать API нескольких соц. сетей, составлять и реализовывать модели для анализа полученных данных
  • Необходимость в наличии действующего аккаунта в соц. сети у пользователя (я считаю, что, несмотря на распространённость, требовать подобные данные от пользователя, всё же, нельзя)
  • Низкая скорость работы, если учитывать анализ с использованием данных друзей

Реализацию, к сожалению, предоставить не могу ибо «секрет фирмы».

2. Данные GeoIP

Наверное, самый простой и доступный каждому способ, однако, для РФ на сегодня, зачастую неточный.

Почему?

Дело в том, что на данный момент большинство существоваших ранее провайдеров регионального уровня было раскуплено и поглощено операторами федерального уровня. И чем же это плохо? А вот чем. Представьте себе ситуацию — в городе «Н» существовало 5 мелких провайдеров. Каждый работал в своём районе города, и соответственно, имел свой пул IPv4 адресов. И даже динамически выданный «белый» IP можно было примерно привязать к определённому району города. Теперь приходит провайдер федерального уровня и покупает все 5 мелких провайдеров с их пулами адресов. Затем он приводит их сеть к некоему общему виду всех сетей этого федерального провайдера. Что мы имеем в итоге? У этого федерального провайдера есть огромное количество клиентов и огромное количество пулов IP, используемых, в зависимости от потребностей, в том или ином регионе. Тоесть теперь адрес, принадлежавший ранее пулу мелкого местного провайдера, может быть выдан клиенту из совершенно другого города, просто потому, что этот пул адресов теперь используется для всех клиентов этого провайдера. А вот сообщать кому и из какой области выдан этот IP никто, естественно, не будет. Тем более, что завтра он может быть выдан ещё кому-то.

Также, никто не помешает пользователю использовать, например, прокси или VPN для выхода в интернет от имени другого IP. В этом случае GeoIP становится абсолютно бесполезным, ибо получит информацию именно об этом прокси или VPN-сервере. То же самое происходит, если провайдер предоставляет своим клиентам доступ в интернет через NAT (а в свете проблем с количством свободных IPv4 адресов это встречается всё чаще и чаще), правда в этом случае, обычно, хотябы можно получить район, область или город.

Такчто полагаться полностью на данные GeoIP всё-таки можно не всегда, хотя этот способ очень удобен — ведь мы получаем информацию практически мгновенно. Для этого, обычно, используется заранее скачанная локальная база данных.

Плюсы:

  • Легко использовать, есть множество реализаций на различных языках
  • Высокая точность (за некоторым исключением, см. выше)
  • Быстрота работы (практически мгновенное получение результата — ведь это всего 1 запрос к базе)

Минусы:

  • Необходимость поддерживать базу IP в актуальном состоянии
  • Отсутствие возможности проверить достоверность полученных данных (только запросами к нескольким базам)
  • Достаточно большой процент ошибочных данных для РФ на данный момент (см. выше)

Описывать «как это сделать» смыла особого не вижу, ибо в сети, и, в т.ч. на хабре, полно подробных описаний. Для получения данных GeoIP существует множество бесплатных библиотек и инструментов. Например, для PHP можно использовать расширение geoip.

3. Использование JavaScript Geolocation API

Достаточно полезный и эффективный метод, но только для мобильных устройств. В случае же со стационарным компьютером — полезен не более чем GeoIP. Дело в том, что в случае мобильного устройства (современный смартфон, планшет и т.д.) будут использоваться все доступные для этого устройства и разрешённые пользователем средства определения местоположения, включая позиционирование по GPS, Wi-Fi и данным от вышек сотовой связи. А вот в случае с домашним ПК, у которого, в большинстве случаев, нет ни мобильной сети (в случае наличия GSM/3G модема данные от него не используются), ни GPS, мы сможем узнать только данные GeoIP, которые нам радостно и сообщит JS. А по поводу их точности я уже писал выше. Хотя, пренебрегать данным способом я бы не стал — ведь всё большее количество людей используют планшеты и телефоны для выхода в интернет.

В итоге данный способ имеет достаточно узкий спектр применения — мобильные устройства. Или если достаточно примерных данных по GeoIP.

Плюсы:

  • Легко реализовать, множество документации и примеров в интернете
  • Точный, т.к. может использоваться как позиционирование по сотовым вышкам, Wi-Fi, GPS
  • Быстрый, т.к. для определения положения используется ПО со стороны клиента

Минусы:

  • На домашних ПК поддерживается не во всех браузерах
  • Требует разрешений пользователя
  • Фактически, применим только к мобильным устройствам
  • Относительно легко подделать данные

Примеры реализации можно посмотреть здесь или здесь.

4. Определение через услуги типа «локатор» от мобильных операторов

Я думаю, некоторые из читающих слышали про эти услуги, кто-то даже пользуется ими, а кому-то приходится их использовать в корпоративной среде. Я говорю об услугах, подобных «Локатор»’у от «яичной» компании и «Координатам» от жёлто-полосатой. Да, эти услуги изначально предназначены для конечных пользователей, но… Что мешает использовать их нам? Положительных моментов при использовании этого способа немного, зато каких — это высокая точность и почти 100% достоверность данных. Зато есть неприятные моменты. Во-первых — эти услуги платные. Во-вторых — необходимость использования номера мобильного телефона при регистрации и требование отправить бесплатную смс на короткий номер… Такое поведение может отпугнуть многих. Да и время получения информации по смс немалое (в рамках веб-приложения). Но, в некоторых случаях, информация подобного рода, да ещё и достоверная, просто необходима. Тем более что этот метод можно использовать как замену подтверждения кодом из смс какого-либо действия. Да и подделать информацию, получаемую таким способом, практически невозможно.

Пример рабочей реализации приводить не буду по тем же соображениям, что и в первом случае, но вкратце опишу как это делается чуть ниже.

Плюсы:

  • Высокая достоверность данных, почти 100%
  • Высокая точность, вне зависимости от испоьзуемого устройства и способа выхода в интернет
  • Автоматически подтверждает номер мобильного телефона

Минусы:

  • Сложность в реализации и поддержке
  • Низкая скорость, т.к. требуется время на отправку/приём смс и ответ от пользователя
  • Не бесплатен (тарифы у операторов на эту услугу весьма «прожорливые»)
  • Необходимо согласие пользователя

Как сделать

Нам понадобятся:

  1. Старый моб. телефон с кабелем, либо 3G/GSM модем, по одному на каждого оператора
  2. Сим карты этих операторов
  3. Некий ПК, желательно с *nix на борту (можно и Windows с cygwin), который будет выполнять функцию эдакого «гео-шлюза»
  4. Немного терпения и времени
  5. smstools3
1) В зависимости от ОС, инструкции могут отличаться, но общий смысл неизменен — необходимо скачать и установить из репозитория ПО пакет SMSTools

На Gentoo это выглядит так:


Если вам нужна статистика отправленных/полученных смс, то:

nogood-work ~ # echo "app-mobilephone/smstools stats" > /etc/portage/package.use/smstools.use 

либо (если у вас все USE-флаги в одном файле):

nogood-work ~ # echo "app-mobilephone/smstools stats" >> /etc/portage/package.use 

Затем ставим из портажа сам smstools:

nogood-work ~ # emerge -v smstools  These are the packages that would be merged, in order:  Calculating dependencies... done! [ebuild  N     ~] app-mobilephone/smstools-3.1.15  USE="-stats" 0 kB  ...  nogood-work ~ # 


На FreeBSD так:


root@kenny:/usr/ports # cd /usr/ports/comms/smstools3 root@kenny:/usr/ports/comms/smstools3 # make install clean 

Для статистики в опциях просто выбрать «STATS»


Можно собрать и из исходников, если для вашей системы нет готового пакета:


nogood-work ~ # wget http://smstools3.kekekasvi.com/packages/smstools3-3.1.15.tar.gz nogood-work ~ # tar -zxvf smstools3-3.1.15.tar.gz -C /usr/local/src nogood-work ~ # cd /usr/local/src/smstools3 nogood-work ~ # make nogood-work ~ # make install 


2) Подключаем модем(ы) и проверяем появились ли устройства последовательного порта в /dev

Для Gentoo:


nogood-work ~ # ls /dev |grep ttyUSB ttyUSB0 ttyUSB1 ttyUSB2 nogood-work ~ # 

Может появиться несколько портов. Обычно нас интересует ttyUSB0, если модем 1. Если больше — то подключаем по очереди. И вот перый из появившихся портов наш.


Для FreeBSD:


root@kenny:~ # ls /dev |grep cuau cuau0 cuau0.init cuau0.lock cuau1 cuau1.init cuau1.lock root@kenny:~ # 

Смысл тот же — первый из нескольких появившихся — наш.


3) Настраиваем SMSTools

smsd.conf может находится как в /etc/ так и в /usr/local/etc/ в зависимости от вашего дистрибутива. Приводим его к подобному виду:

#Список активных "модемов". Если вы планируете использовать #несколько операторов, то, соответственно, перечисляем здесь #модемы для каждого оператора, у меня только для одного devices = GSM1 #Куда писать логи. Если закомментировать то по-умолчанию #пишет в syslog. Но в этом случае не получится использовать #такую классную вещь, как smart_logging. logfile = /var/log/smsd/smsd.log #Уровень ошибок. loglevel = notice #Хранить входящие в UTF-8. Работает не со всеми модемами, но лучше включить incoming_utf8 = yes #Записывать историю перекодировок в логах. На всякий случай включаем. log_charconv = yes #Наличие даты в имени файла. Вообще кому как удобно, #но с этой опцией файлы легче находить по времени date_filename = 1 #Приоритет получения смс перед отправкой receive_before_send = yes #Очень полезная, на мой взгляд, функция. Суть в том, что в лог #по-умолчанию пишутся сообщения с уровнем, указанным выше. #А вот в случае ошибки создаётся файлик с изменённым именем #из logfile вида <name>_trouble.log в который пишется всё с уровнем debug smart_logging = yes #Ну и настройка каталогов спулера failed = /var/spool/sms/failed sent = /var/spool/sms/sent phonecalls = /var/spool/sms/calls stats = /var/spool/sms/stats  #А вот настройка для модема. Лучше искать под конкретную модель. [GSM1] #Имя COM-порта device = /dev/ttyUSB0 #Использовать ли для приёма СМС incoming = yes #Способ проверки памяти СМС. Подробности лучше глянуть на оф. сайте. check_memory_method = 2 #Обязательно закомментить, т.к. иначе не видать нам русского языка #decode_unicode_text = yes #Могут понадобится для вашего модема. Вот это лучше погуглить. #init = AT+CSCS="UCS2" #init2 = AT+CSCS="UCS2" #Автоматически собирать смс из нескольких частей. Крайне рекомендую. internal_combine = yes #Сбрасывать входящие звонки. А зачем они нам? hangup_incoming_call = yes #Скрипт для обработки событий. Содержимое будет ниже. eventhandler = /etc/smsd/trsms.sh #Скрипт для обработки USSD команд. Я не использовал, но можно #использовать для получения остатка на балансе. #eventhandler_ussd = #Номер. Если будете использовать несколько модемов указывать надо. #По нему определяется через какой модем отправлять смс. number = 79185568942 #Что делать со входящими звонками - определять номер. Необязательно. phonecalls = clip #Отчёт о доставке. Нам не нужен. #report = yes #Для моего модема нужно было включить, чтобы небыло ошибок в логе. signal_quality_ber_ignore = yes 
4) Создаём файлик trsms.sh (обработчик событий)
#!/bin/bash status="$1" file="$2"  case "$1" in   RECEIVED)      header=`head -12 $file | grep -e "^From: " -e "^Sent: " -e "^Received: "`     from=`head -12 $file | grep -e "^From: " | awk '{print $2}'`      if grep "Alphabet: UCS2" $file > /dev/null > /dev/null; then         message=`tail -n +14 $file | iconv -f UCS-2BE -t UTF-8`     else         message=`tail -n +14 $file`     fi     #echo -e "$message" | mail -s "Incoming SMS from +$from" admin@cashrussia.ru     echo -e "$header\n$message\n" >> /var/log/smsd/sms.log      if echo $message | grep "Запрос на авторизацию отправлен абоненту" > /dev/null > /dev/null; then         abon=`echo $message | awk 'BEGIN{ FS = "абоненту " } $2 { print substr($2, 2, 11) }'`         echo -e "\n> Запрос\t$abon" >> /var/log/smsd/location.log     fi      if echo $message | grep " находится по адресу " > /dev/null > /dev/null; then         abon=`echo $message | awk 'BEGIN{ FS = "Абонент " } $2 { print substr($2, 2, 11) }'`         adres=`echo $message | awk 'BEGIN{ FS = "адресу " } $2 { print substr($2,0,index($2, " в радиусе")) }'`         region=`echo $adres | awk 'BEGIN{ FS = ", " } $1 {print $1}'`         echo -e "\n> Ответ\t$abon\t$adres\tРЕГИОН: $region" >> /var/log/smsd/location.log     fi     ;; esac 

Это пример с минимальным функционалом. Пишет в лог запросы и полученные ответы для «яичного» оператора. По-хорошему ещё надо добавить условие по номеру, с которого пришло сообщение, на основе переменной from. В нём же можно будет определять и оператора. Номера у разных операторов, как правило, разные.
Не забываем дать права на запуск пользователю, из под которого будет работать smsd.

5) Запускаем демон smsd и добавляем его в автозагрузку

Для Gentoo:


nogood-work ~ # /etc/init.d/smsd start nogood-work ~ # rc-update add smsd default 


Для FreeBSD:


root@kenny:~ # echo "smsd_enable=\"YES\"" >> rc.conf root@kenny:~ # service smsd start 


Смотрим логи. Если всё хорошо и нет сообщений об ошибках, то переходим к следующему шагу.

6) Пробуем отправить смс на свой телефон
nogood-work ~ # sendsms 79xxxxxxxxx 'текст' 

Если смс прошло успешно — можно пробовать отправить смс на заветный номер услуги с соответствующим текстом, а затем проверить логи.
Далее можно будет просто вызывать из вашего скрипта команду sendsms <номер> "<текст>" и проверять, например, по крону наличие ответа по нужному номеру в файле с логами смс.

Заключение

Каждый из этих способов подходит для каких-то определённых целей и условий, и вам решать, что именно использовать. Конечно, здесь рассмотрены далеко не все способы определения местоположения. Я описал только те, что опробовал сам и считаю наиболее эффективными. Также, для достижения большей эффективности, я бы рекомендовал комбинировать их. Так это делается в нашем проекте. На этом всё. Надеюсь кому-нибудь данная информация окажется полезной.

ссылка на оригинал статьи http://habrahabr.ru/post/193372/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *