Вход на сайт

МЕДИАМЕТРИКА

Облако тегов

Автоматическая аутентификация Android-устройства в Wi-Fi Московского Метро

Аватар пользователя dazed

Как известно, практически во всех вагонах Московского Метро действуют Wi-Fi точки доступа, с помощью которых пользователи могут получить доступ в интернет и приятно скоротать время поездки в метро с работы домой: почитать новости, проверить почту, посмотреть котиков на YouTube и т.д.

Если в метро вы не частый гость, то подобная схема может и не вызвать у вас раздражения, однако при ежедневном использовании она все таки надоедает, поэтому, как говорил один известный и харизматичный политик: «Хватит это терпеть!», сегодня мы будем автоматизировать аутентификацию в Московском метро.

надеюсь, комунить пригодится ...)

Как известно, практически во всех вагонах Московского Метро действуют Wi-Fi точки доступа, с помощью которых пользователи могут получить доступ в интернет и приятно скоротать время поездки в метро с работы домой: почитать новости, проверить почту, посмотреть котиков на YouTube и т.д.

Каждому устройству, прежде чем ему будет предоставлен доступ к сети интернет, необходимо аутентифицироваться. В первый раз пользователю на указанный номер телефона посылается СМС с кодом, после чего система запоминает MAC-адрес устройства и в дальнейшем пользователю для аутентификации требуется только нажать на ссылку «Войти в интернет» и немного подождать.

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

Если в метро вы не частый гость, то подобная схема может и не вызвать у вас раздражения, однако при ежедневном использовании она все таки надоедает, поэтому, как говорил один известный и харизматичный политик: «Хватит это терпеть!», сегодня мы будем автоматизировать аутентификацию в Московском метро.

В первую очередь нам понадобится приложение Tasker. Раздобыть его можно тут (за небольшую денежку), ну или где-нибудь тут (на свой страх и риск). Лично я предпочел первый вариант и не пожалел.

Tasker — приложение, которое позволяет в зависимости от определенных условий (дата/время/местоположение/состояние устройств/показания датчиков и т.д.) производить определенные действия (отправку сообщений/вывод уведомлений/включение-отключение устройств/отрисовка простеньких интерфейсов и т.д.). Списки и условий, и действий просто огромны и зависят от версии Android и аппаратного оснащения устройства, так что приводить их полностью смысла нет.

Итак, после запуска Tasker, в первую очередь нужно перевести интерфейс на английский язык, ибо перевод тут хромает на обе ноги: Настройки->Интерфейс->Язык->English и перезапустить приложение. Теперь перед нами есть четыре вкладки:

  • Profiles — профили управляют связью между состоянием устройства/различными событиями и задачами;
  • Tasks — задачи описывают последовательность действий, которые необходимо выполнить;
  • Scenes — сцены это как бы самодельные формы, которые задачи могут создавать и настраивать, и контролы на которых могут запускать задачи;
  • Vars — список глобальных переменных, которые могут быть использованы для хранения данных между запусками задач.



Перейдем на закладку Tasks и создадим новую задачу, назвав ее Metro Auth:



В открывшемся окне нам необходимо для начала определить несколько переменных. Переменные определяются следующим образом:

  • Variable name — имя переменной, должно начинаться с символа % и состоять из строчных букв. Если в имени переменной будет хоть одна заглавная буква, то переменная станет глобальной, а нам это ни к чему;
  • To — значение переменной.


Так вот, нам необходимо создать следующие переменные:

  • %url — содержит ссылку на страницу, по которой мы будем тестировать нужна ли аутентификация или нет. Чем меньше объем передаваемых данных при этом — тем лучше (тело страницы все равно не нужно). С протоколом HTTPS возможны проблемы, так что лучше использовать HTTP;
  • %forms — содержит список идентификаторов HTML-форм, которые мы будем использовать для аутентификации. На момент написания статьи корректное значение — 'auth-form,hidden_form', однако если ребята из московского метро вдруг что-то изменят, я хотел бы показать как составить такой список самостоятельно, так что пока в качестве значения поставим один пробел (пустые переменные недопустимы);
  • %debug — эта переменная, при задании значения, отличного от нуля, будет вызывать показ дополнительной отладочной информации, которая поможет нам составить вышеупомянутый список форм.


Помимо простых действий, Tasker предоставляет нам возможность писать скрипты произвольной сложности с помощью нескольких инструментов. Мы будем использовать простой JavaScript:



Здесь необходимо выставить максимальный Timeout выполнения скрипта — 50 секунд, просто на всякий случай. Галочка Auto Exit отвечает за автоматическое завершения действия после завершения основного потока скрипта. В случае если используются асинхронные запросы (наш случай) или функция setTimeout, эту галочку необходимо снимать, а завершение действия определять самостоятельно с помощью функции exit();.

Сам скрипт я представлю в двух вариантах форматирования: приличное форматирование нужно если хочется рассмотреть скрипт, не сломав глаза, и форматирование под узкий экран позволяет скрипту выглядеть более-менее прилично на узком экране телефона. Изначально скрипт набирался на телефоне в «узком» варианте, и уже потом я переформатировал его для статьи:

Скрипт в приличном форматировании
function getUrl(url1,url2){
    url1=url1.split('?')[0];
    return url2.length?
        (/^http(s?):\/\//i.test(url2)?url2:
            (url2[0]=='/'?url1.split('/').slice(0,3).join('/')+url2:url1.split('/').slice(0,-1).join('/')+'/'+url2)
        ):url1;
}

function getVars(form,tag){
    vars='';
    fields=form.getElementsByTagName(tag);
    for(i=0;i<fields.length;i++)
        vars=vars+(i?'&':'')+fields[i].name+'='+fields[i].value;
    return vars;
}

function submit(xhr,request,form){
    request.url=getUrl(request.url,form.action);
    request.method=form.method;
    vars1=getVars(form,'input');
    vars2=getVars(form,'textarea');
    request.vars=vars1||vars2?(vars1?vars1:'')+(vars1&&vars2?'&':'')+(vars2?vars2:''):null;
    getPage(request,processPage,xhr);
}

function processPage(xhr,request){
    redir=xhr.getResponseHeader('Location');
    if(redir){
        if(redir==request.url) finalize('Ошибка: циклическое перенаправление');
        else{
            log('Перенаправление\n\n');
            getPage({'url':redir},processPage,xhr);
        }
    } else {
        forms=local('forms').split(',');
        id=null;
        for(i=0;i<forms.length;i++)
            if(xhr.response.getElementById(forms[i])) id=forms[i];
        if(id)submit(xhr,request,xhr.response.getElementById(id));
        else if(Number(local('debug'))){
            log('Формы на странице:\n');
            forms=xhr.response.getElementsByTagName('form');
            if(forms.length)
                for(i=0;i<forms.length;i++)
                    log((i?', "':'"')+forms[i].id+'"');
            else log('отсутствуют');
            finalize();
        } else finalize('Аутентификация успешна');
    }
}

function checkConn(xhr,request){
    redir=xhr.getResponseHeader('Location');
    if(redir){
        log('Перенаправление\n\n');
        getPage({'url':redir},processPage,xhr);
    } else {
        log('Аутентификация не требуется');
        finalize();
    }
}

function log(txt){
    logs=logs+(txt?txt:'');
}

function requestToText(request){
    return 'URL: '+request.url+'\nMethod: '+request.method+', Vars: '+request.vars+'\n';
}

function finalize(txt){
    log(txt);
    if(Number(local('debug'))) alert(logs);
    else if(txt) flashLong(txt);
    exit();
}

function getPage(request,func,xhr){
    if(!request.method) request.method='GET';
    if(!request.vars) request.vars=null;
    if(!xhr){
        xhr=new XMLHttpRequest();
        xhr.responseType="document";
        xhr.timeout=20*1000;
    }
    xhr.open(request.method,request.url,true);
    xhr.onload=function(){
        if(xhr.status==200 || xhr.status==401){
            log (requestToText(request)+'HTTP status: '+xhr.status+' '+xhr.statusText+'\n');
            func(xhr,request);
        } else {
            log(requestToText(request));
            finalize('Ошибка HTTP: '+xhr.status+' '+xhr.statusText);
        }
    }
    xhr.onerror=function(){
        log(requestToText(request));
        finalize('Ошибка: отсутствует соединение');
    }
    xhr.ontimeout=function(){
        log(requestToText(request));
        finalize('Ошибка: таймаут соединения');
    }
    xhr.send(request.vars);
}

logs='';
getPage({'url':local('url')},checkConn);

Скрипт в форматировании под узкий экран
function getUrl(url1,url2){
  url1=url1.split('?')[0];
  return url2.length?
    (/^http(s?):\/\//i.test(url2)?
      url2:
        (url2[0]=='/'?
        url1.split('/').slice(0,3).join('/')+url2:
        url1.split('/').slice(0,-1).join('/')+
      '/'+url2)
    ):url1;
}

function getVars(form,tag){
  vars='';
  fields=form.getElementsByTagName(
    tag);
  for(i=0;i<fields.length;i++)
    vars=vars+(i?'&':'')+fields[i].name+
      '='+fields[i].value;
  return vars;
}

function submit(xhr,request,form){
  request.url=getUrl(request.url,
    form.action);
  request.method=form.method;
  vars1=getVars(form,'input');
  vars2=getVars(form,'textarea');
  request.vars=vars1||vars2?
    (vars1?vars1:'')+
    (vars1&&vars2?'&':'')+
    (vars2?vars2:'')
    :null;
  getPage(request,processPage,xhr);
}

function processPage(xhr,request){
  redir=xhr.getResponseHeader(
    'Location');
  if(redir){
    if(redir==request.url)
      finalize('Ошибка: циклическое '+
        'перенаправление');
    else{
      log('Перенаправление\n\n');
      getPage({'url':redir},processPage,
        xhr);
    }
  } else {
    forms=local('forms').split(',');
    id=null;
    for(i=0;i<forms.length;i++)
      if(xhr.response.getElementById(
          forms[i]))
        id=forms[i];
    if(id)submit(xhr,request,
      xhr.response.getElementById(id));
    else if(Number(local('debug'))){
      log('Формы на странице:\n');
      forms=xhr.response.
        getElementsByTagName('form');
      if(forms.length)
        for(i=0;i<forms.length;i++)
          log((i?', "':'"')+forms[i].id+'"');
      else log('отсутствуют');
      finalize();
    } else finalize(
      'Аутентификация успешна');
  }
}

function checkConn(xhr,request){
  redir=xhr.getResponseHeader(
    'Location');
  if(redir){
    log('Перенаправление\n\n');
    getPage({'url':redir},processPage,
      xhr);
  } else {
    log('Аутентификация не '+
      'требуется');
    finalize();
  }
}

function log(txt){logs=logs+(txt?txt:'');}

function requestToText(request){
  return 'URL: '+request.url+
    '\nMethod: '+request.method+
    ', Vars: '+request.vars+'\n';
}

function finalize(txt){
  log(txt);
  if(Number(local('debug'))) alert(logs);
  else if(txt) flashLong(txt);
  exit();
}

function getPage(request,func,xhr){
  if(!request.method)
    request.method='GET';
  if(!request.vars)request.vars=null;
  if(!xhr){
    xhr=new XMLHttpRequest();
    xhr.responseType="document";
    xhr.timeout=20*1000;
  }
  xhr.open(request.method,
    request.url,true);
  xhr.onload=function(){
    if(xhr.status==200 ||
        xhr.status==401){
      log (requestToText(request)+
        'HTTP status: '+xhr.status+' '+
        xhr.statusText+'\n');
        func(xhr,request);
    } else {
      log(requestToText(request));
      finalize('Ошибка HTTP: '+
        xhr.status+' '+xhr.statusText);
    }
  }
  xhr.onerror=function(){
    log(requestToText(request));
    finalize('Ошибка: отсутствует '+
      'соединение');
  }
  xhr.ontimeout=function(){
    log(requestToText(request));
    finalize('Ошибка: таймаут '+
      'соединения');
  }
  xhr.send(request.vars);
}

logs='';
getPage({'url':local('url')},checkConn);

Набор скрипта с телефонной клавиатуры, к сожалению, не располагает к комментариям, но я вкратце опишу алгоритм:

  1. Пытаемся загрузить страницу, указанную в переменной %url
  2. Если в ответе нет HTTP-заголовка Location, значит нас не перенаправляют, а значит в данный момент аутентификация не нужна, выход
  3. Загружаем страницу, на которую нас направили.
  4. Если есть заголовок Location, возвращаемся к п.3
  5. Если на странице есть форма из списка в переменной %forms, изображаем ее submit и возвращаемся к п.3
  6. В остальных случаях — мы успешно прошли аутентификацию



После завершения ввода скрипта, у нас получилась вот такая задача:



С помощью первой иконки в нижнем ряду можно попробовать ее запустить. Теперь самое время спускаться в метро, чтобы настроить ее!

В метро, подключившись к точке доступа, пробуем запустить задачу. Если нет явных проблем с доступностью серверов, то мы увидим сообщение, похожее на то, что изображено на следующем рисунке слева. Внизу мы видим идентификатор формы, которая есть на последней загруженной странице — auth-form. Эта форма — явно наш клиент, вносим ее название в переменную %forms и запускаем задачу еще раз, получаем примерно то, что изображено на следующем рисунке в центре. Новый идентификатор формы — hidden_form. Добавляем ее в переменную %forms, теперь ее значение будет 'auth-form,hidden_form'. Запускаем задачу еще раз и видим примерно то, что изображено на следующей рисунке справа — либо будет форма без идентификатора, либо пометка «отсутствуют» (зависит от ветки метро). Если теперь запустить браузер, будет понятно, что аутентификацию мы прошли. Присваиваем переменной %debug значение «0», и закрываем задачу — тут мы закончили.



Теперь дело за малым — настроить автоматический запуск задачи при подключении к нужной точке доступа. Переходим на закладку Profiles и создаем новый профиль, который будет активироваться после подключения к точке доступа московского метро. После того, как закончим формировать описание точки доступа, Tasker спросит нас с какой задачей связывать это профиль, выбираем, естественно, Metro Auth.



Еще одни нюанс: хотя и редко, но аутентификация все таки слетает, хотя отключения от точки и не происходило. Если не было отключения, не было и переподключения, а значит Tasker не запустит задачу повторно, поэтому мы настроим Tasker так, чтобы аутентификация автоматически проверялась каждые 2 минуты (минимальный возможный интервал), для этого нам надо долгим нажатием на уже сконфигурированное условие вызвать меню, в котором добавить временное условие, в котором установить интервал.



Ну вот и все. Отныне и до тех пор, пока не придется менять идентификаторы в переменной %forms, алгоритм ваших действий при заходе в вагон следующий:

  1. Включить Wi-Fi;
  2. Дождаться сообщения «Аутентификация завершена» на экране;
  3. Загадочно улыбнуться и заняться своими делами.

спасибо Hormiga далектй незнакомый друг) 

Фонд поддержки авторов AfterShock

Комментарии

Аватар пользователя Ficher
Ficher(3 года 1 месяц)(19:47:53 / 20-08-2015)

Ого... как будто на сайт "КомтьюТерра"попал )))

Аватар пользователя VGlaz
VGlaz(3 года 3 месяца)(19:50:26 / 20-08-2015)

Отныне и до тех пор, пока не придется менять идентификаторы в переменной %forms, алгоритм ваших действий при заходе в вагон следующий:

А они на разных ветках метро не отличаются?

Аватар пользователя geoman
geoman(5 лет 9 месяцев)(19:51:16 / 20-08-2015)

Зачем всё это?

Аватар пользователя dazed
dazed(2 года 4 месяца)(19:57:17 / 20-08-2015)

вы не знаете зачем аутентификация?

Комментарий администрации:  
*** Заподозрен в ссылочном спаме, под наблюдением ***
Аватар пользователя Safron
Safron(5 лет 7 месяцев)(19:52:26 / 20-08-2015)

Офтопиш камрад, не хорошо

Аватар пользователя dazed
dazed(2 года 4 месяца)(20:03:04 / 20-08-2015)

лишь бы комунить пригодилось)

иногда ;) приходится прибегать к более простым мммм ... уловкам, но  они не имеют широкого применения и пользы

Комментарий администрации:  
*** Заподозрен в ссылочном спаме, под наблюдением ***
Аватар пользователя agafonoff2000
agafonoff2000(5 лет 11 месяцев)(19:53:03 / 20-08-2015)

проще готовое приложение бесплатное для авторизации из 4pda скачать. (не рекламма)

Аватар пользователя let_it_be
let_it_be(3 года 10 месяцев)(20:02:52 / 20-08-2015)

Забавный комментарий одного "москвича" после того, как я ему сообщил о hot spot идентификации в московском метро:

http://aftershock.news/?q=comment/1870264#comment-1870264

Аватар пользователя dazed
dazed(2 года 4 месяца)(20:33:22 / 20-08-2015)

да, это тот еще штемп. здесь запрещено с такими обчаться на доступном языке(

Комментарий администрации:  
*** Заподозрен в ссылочном спаме, под наблюдением ***
Аватар пользователя Красный аноним

А есть добрые ребята, которые делают полезное дело, собирая в метро mac-адреса устройств, на которых не выключен wi-fi. Потом можно на своём устройстве просто подменять mac на любой из такой базы и вполне анонимно пользоваться интернетом в метро без регистрации через смс.

Аватар пользователя dazed
dazed(2 года 4 месяца)(21:27:01 / 20-08-2015)

дааааа ..... блин, тут  я лоханулся(

я было прочитав заголовок, решил(ссзб) что для каждого подключении к сети клиент получает разовый идентификатор по смс, которым  вафельный клиент аутентифицируется в сети.

а аказыватца

В первый раз пользователю на указанный номер телефона посылается СМС с кодом, после чего система запоминает MAC-адрес устройства

йипона мать(

ну, ладно, droid/firesheep  в mcdonalde это одно,  но тупо безо всякой аутентификации и по идентификации по маку предоставлять доступ...

блин, вас там наверна ломают все кому не лень

ваще в таких сетях тока  видосы и серфинг.

Комментарий администрации:  
*** Заподозрен в ссылочном спаме, под наблюдением ***
Аватар пользователя PavelCV
PavelCV(5 лет 2 недели)(20:05:29 / 20-08-2015)

А зачем с телефона, да ещё в метро, выходить в интернет?

Только ради котиков?

Вот раньше, до эпохи андроида, нормальные люди в метро читали книги. Некоторые спали. А сейчас?   :-)

Аватар пользователя XS
XS(3 года 6 месяцев)(20:32:41 / 20-08-2015)

В данный момент как раз еду в московском метро, Aftershock читаю :)

Аватар пользователя Красный аноним

Многие уже срослись со смартфонами.

Я, как дикарь в глазах современников, вожу смартфон в сумке и в метро им не пользуюсь, а читаю книгу или по сторонам глазею.

Аватар пользователя Rashad_rus
Rashad_rus(5 лет 9 месяцев)(20:06:18 / 20-08-2015)

Достаточно поставить NetScan и тупой консольный шедулер, типа crond - всё бесплатно и делается быстро и просто. Зачем городить огород?!

Достаточно забить, чтобы раз в пять минут включался WiFi и "обнюхивал эфир" для поиска нужной точки доступа(или по маске имени), и в зависимости от результата выполнял нужные действия - это проще пареной репы!

Аватар пользователя Не тот человек

Вот как. Мы перестали смотреть по сторонам и под ноги, мы смотрим в интернет.

В Германии есть такое выражение, " Luxus,- nicht erreichbar zu seien " . В переводе как " роскошь быть в не зоны доступа ".

На сегодняшний день, немецкий толковый словарь можит размножится ещё одним слэнговым словом "Smombis", толкование таково " люди как привязанные к своим телефонам и не смотрящие куда идут, смотрят только в телефон" словообразование аля- телефонный зомби.... 4-ое место, 6% голосов.

Источник: http://www.jugendwort.de

Неужели?! Люди "ТАК" не могут без интернета во время дороги? 

Аватар пользователя geoman
geoman(5 лет 9 месяцев)(20:49:08 / 20-08-2015)

Повторюсь: Зачем всё это? Для больных на голову?

Куда интереснее рассматривать окружающих людей. Да, и, вообще, вне дома и работы надо быть "здесь и сейчас", а не в свистоперделке. Просто совет.

Аватар пользователя dazed
dazed(2 года 4 месяца)(21:32:58 / 20-08-2015)

новости удобно смотреть именно в метро, не за рулем же?

а на окружающих лучше смотреть за рулем, но упаси боже не в метро.

как до меня, то меня ваще от них тошнит, и никакого интнреса их рассматривать нет и быть не может.

"здесь и сейчас",

согласен, я понимаю это как быть в адекватной псих форме, а не в тупом коматозе перевозимой мебели.

Комментарий администрации:  
*** Заподозрен в ссылочном спаме, под наблюдением ***

Лидеры обсуждений

за 4 часаза суткиза неделю

Лидеры просмотров

за неделюза месяцза год

СМИ

Загрузка...