smsGate-1.0.0. Авторизация через sms

На самом деле компонент предназначен не только для авторизации через sms, а в принципе для отправки sms. Но в первую очередь он нужен был именно для настройки двухфакторной авторизации. И вот как раз в плане вклинивания в процесс авторизации я узнал много нового (хотя и так знал не мало). Был немного расстроен…
MODX расстроил меня неидеальностью своего процессора авторизации. Вот смотрите, вот здесь вызывается событие, на которое логично навесить плагин, на уровне которого можно было бы реализовывать свою логику.
$canLogin = $this->fireOnAuthenticationEvent();Но проверка пароля идет только на следующей строчке.$preventLogin = $this->checkPassword($canLogin);То есть в момент срабатывания плагина мы еще не знаем верный пароль или нет. В итоге приходится в плагине выполнять дополнительную проверку пароля.
Но это не главная проблема. Главная проблема в том, что MODX не проверяет успех у вас в плагине или нет, а точнее он просто возвращает false в случае если не успех.
При этом, если внимательно изучить логику, видно, что в случае возникновения ошибок в плагине, пользователь вопреки всякой логике будет на самом деле авторизован, а не послан, так как пароль просто не будет проверяться. Вот куски кода:
public function checkPassword($rt) {
/* check if plugin authenticated the user */
if (!$rt || (is_array($rt) && !in_array(true, $rt))) {
/* check user password - local authentication */
if (!$this->user->passwordMatches($this->givenPassword)) {
$this->failedLogin();
return $this->modx->lexicon('login_username_password_incorrect');
}
}
return false;
}$canLogin = $this->fireOnAuthenticationEvent();
$preventLogin = $this->checkPassword($canLogin);
if (!empty($preventLogin)) {
return $this->failure($preventLogin);
}Как видите, только в случае успеха выполнения плагина, проверяется пароль. А если нет, то возвращает false. А false !== !empty(false).Можете сами проверить. Создайте у себя плагин на событие OnWebAuthentication и пропишите в нем $modx->event->_output = 'false';
А в консоли выполните такой код:
$modx->switchContext('web');
$response = $modx->runProcessor('security/login', array(
"username" => "test",
"password" => "asdasdasddqwdqwdq",
));
print_r($response->getResponse());Пользователь само собой должен существовать.Как результат: авторизация. joxi.ru/Y2LjLVESn3pqXr
Надеюсь, кто-нибудь отправит багфикс. Если нет, я позже отправлю.
В общем, вот эти косяки не позволили через плагин реализовать, пришлось расширять процессор и через него работать. Вот код процессора.
Напомню, что компонент Login не использует процессор security/login, там у него все на уровне хуков делается.
Второй неприятный момент был уже с самими sms-шлюзами.
Неприятность 1. Первым делом глаз положил на iqsms.ru/
Вроде и сайт не плохой, и API есть в форматах XML и JSON, да и вообще вроде как все ОК. Сделал я их, SMSки отправляются… Но когда пошел пополнять баланс, а там раз, и минимальный платеж 2000 рублей… Вот куда столько? Я так прикинул, если пара человек в день авторизуется на сайте (шлет штук 5 смс в день), так это на смски вложение на пару лет минимум:) В общем, пошел я искать sms-провайдера, где пополнять можно на меньшую сумму. Нашел letsads.com/ Эти хоть на 5 рублей пополняй. Правда при оплате картой комиссия составила 14%, буду еще смотреть что при оплате яндекс.деньгами будет, там два провайдера платежей у них.
С этим провайдером только маленькая досада, что API в XML-формате, но это мелочи. К слову, я вот как-то писал уже про MODX-овый рест-клиент, вот здесь покажу как приятно через него работать и в таких случаях.
Вот вызов с передачей данных в JSON-формате:
if(!$client = $modx->getService('rest.modRestCurlClient')){
return "Не был получен CURL-клиент";
}
$params = array(
"statusQueueName" => $statusQueueName,
"statusQueueLimit" => $limit,
);
$options = array(
"contentType" => "json",
);
if($login){
$options[modRestClient::OPT_USERPWD] = "{$login}:{$password}";
}
if(
$result = $client->request("{$host}:{$port}", '/statusQueue/', 'POST', $params, $options)
AND $result = json_decode($result, 1)
){
return $result;
}Вот здесь и данные при отправке кодируются в JSON, и авторизация сразу передается.А чтобы этот же запрос ушел не в JSON, а в XML, надо просто «contentType» => «json» заменить на «contentType» => «xml».
Правда удобно? А полученный XML-ответ легко перевести в массив $array = modRestArrayToXML::toArray($result);
Неприятность 2. Международные и прямые sms-каналы.
Вот это вообще засада… У многих sms-провайдеров цены указаны в районе +-40 копеек. Но как оказалось, это при передаче по так называемым «Международным каналам». На самом деле это интернет-каналы. Потери в таких случаях весьма серьезные (сами провайдеры заявляют до 95% при массовых рассылках). Так что хочешь не хочешь, а надо переключаться на прямой канал. А там цена уже взлетает сразу в 3-4 раза, то есть средняя цена 1.60-1.90 руб за смс. При чем в letsads.com/ информация об этом в личном кабинете выводится очень заметно. А на iqsms.ru/ я этого не увидел нигде. Писал запрос в саппорт. Ответили… joxi.ru/8AnXDv9uqBMpdm
В общем, подводных камней оказалось масса. Здесь прошу всех, у кого есть какой опыт здесь, поделиться, какие sms-провайдеры кто юзает и с какими еще подводными камнями или фишками сталкивался.
Напоследок еще немного о компоненте: Пока код работы с iqsms.ru заморожен за ненадобностью, но в дальнейшем планирую реализацию поддержки множества провайдеров, так что этот провайдер тоже вернется в строй. Пока же основной провайдер — letsads.com/
Компонент логирует отправляемые sms-ки, и потом можно по ним запрашивать статусы. При получении статуса информация обновляется и в БД.
Пока стоимость пакета составляет 1490 рублей и такой останется, пока компонент не получит более оформленный и обширный функционал. Со своей стороны гарантирую информационную и прочую помощь в его использовании. А использовать его можно где угодно, включая уведомления о смене статуса заказов и т.п.
Доступен в modstore.pro.
P.S. Кто хочет опробовать в действии, у нас на сайте если в профиле указать номер телефона, то авторизация становится двухфакторной. Можете посмотреть как это работает.
Комментарии: 43
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
Прости, не удержался — фраза двусмысленной получилась, исправь пожалуйста…
Что включает в себя компонент для работы? Сниппет? Интерфейс в админке?
Fi1osofСлужбу. То есть
Еще есть таблица в БД, куда складываются отправляемые СМСки и их статусы. Есть метод проверки статуса СМС, при этом ее статус в БД обновляется при запросе.
Будут продажи и будут пожелания: будут интерфейсы и прочие плюшки.
Fi1osofНочью пытался воспроизвести на чистом MODX 2.5.2 — не удалось.
Fi1osofFi1osofFi1osofFi1osofИз минусов:
Все акции, подарочные сертификаты и т.п. не работают для юр. лиц.
Ребята сидят в Омске, сдвиг рабочего времени +3 ч от Москвы.
Fi1osofFi1osofFi1osofFi1osof1. событие «OnWebAuthentication» на самом деле правильнее назвать было бы «OnBeforeWebAuthentication»
и в этой роли оно свой функционал отрабатывает идеально.
У меня, например, сейчас с помощью этого события реализован функционал авторизации по ссылке. Пришла ссылка на email — тыц на нее — и ты уже залогинен.
2. По поводу "$modx->event->_output" вообще претензия странная.
«Я туда сую неверное значение и MODX плохо работает». Так не суйте неверное.
Если в процессе работы плагина выходит, что пользователь достоин авторизации, то делаем в иных случаях не трогаем. И все работает как надо.
3. Добавить событие «OnAfterWebAuthentication» было бы полезно
Fi1osofНо плюс к слову, аргументирую.
Вот смотрите, процессор обновления документа расширяет базовый процессор modObjectUpdateProcessor. В этом процессоре есть метод fireBeforeSaveEvent(). Если у текущего процессора есть свойство $this->beforeSaveEvent, то на это событие вызывается плагин. В процессоре обновления документа resource/update это свойство есть, и когда процессор отрабатывается, выполняется и плагин. И в плагине можно вернуть сообщение об ошибке. И на это в базовом процессоре прописан корректный обработчик. Обратите внимание, что в этом обработчике прописано присвоение возвращаемой переменной $preventSave. И внимательно посмотрите на эту конструкцию:
Если $preventSave не пустое, то возвращается ошибка. Вот это правильная работа плагина. Создайте плагин на событие OnBeforeDocFormSave и пропишите $modx->event->_output = «false»; и попробуйте сохранить документ. Что получите? Ошибку.
Вас смущает 'false'? Так вот, это не неверное значение, как вы выразились, а произвольное строчное значение, то есть сообщение. И это сообщение может быть более непрограммиступонятное, и даже можно подсвечивать произвольные поля.
Вот это корректная работа плагина.
А что у нас в security/login прописано? Тупо возврат логического false. Из-за чего корректной обработки не происходит.
Вы просто выполняете дополнительные действия, никак не влияя на ход выполнения процессора. А вы попробуйте в этом своем плагине вернуть ошибку пользователю и прервать его авторизацию.
У нас с вами разные понятия «как надо». Сделаете вы $modx->event->_output = true; или не сделаете ничего, результат не поменяется в принципе. А вы сделайте так, чтобы поменялся.
А вы поищите хорошенько, может что-то подобное найдете.
Чушь, что плагин OnAfterWebAuthentication неверно работает и плагин свою логику отрабатывает на 5+
он сейчас работает для обхода проверки пароля
для того что бы можно было авторизовать пользователя не зная его пароля
ферштейн?
вы же его пытаетесь использовать для другого совершенно. Для запрета авторизации.
такой функционал был бы полезен, слов нет. Но этот плагин не для этого.
поэтому не фикс надо отправлять, а апдейт. Добавить еще одни плагин для нужного вам функционала
Про
и
Сами себе противоречите )))
Если вы не сделаете ничего, то плагина и нет как бы, и тогда с неверным логин/паролем пользователя не авторизуют
А если сделаете «modx->event->_output = true;» то проверки пароля не будет
и пользователь авторизуется только по логину.
Про
OnWebLogin — не то, в этот момент пользователь уже авторизован, а нужно этого не допустить
Fi1osofЕсли примут, то можно будет не только разрешать авторизацию без пароля (если возвращать true), но и можно будет выбрасывать собственные ошибки. Так будет гораздо гораздее.
Как раз этого и хотел не допустить, и это и решает данный PR. Его неидеальность только в том, что придется в нем в случае чего все равно проверять пароль, если надо проверить пароль (так как сейчас проверка пароля идет уже за пределами вызова этого события), но это не страшно. Теперь, если вы считаете, что все проверки пройдены, но не надо позволить пользователю авторизоваться, можно будет просто вернуть сообщение ошибки (не true и не false).
он конечно безобидный, в том смысле что никогда не выполнится )))
но полезнее, если работать будет:
вместо
if ($rt && (is_array($rt) && !in_array(true, $rt)))
надо
if ($rt && is_array($rt) && !in_array(true, $rt, true))
ps Изящно исправили. аж восхитился. Серьезно!
Fi1osofАнтонМожет есть способ отправлять смс посредством обычной связи.
Есть же GSM модули всякие.
Fi1osofХотя конечно, если где-то что подешевле нароется, будет замечательно.
В хуке доступны все поля формы.
Fi1osofИ как было заявлено в описании компонента, с нашей стороны помощь в настройке. Так что если не справитесь самостоятельно, поможем.
Fi1osofFi1osofFi1osofБелые смс-ки на летсадс стоят 1.70. Это средняя по рынку стоимость.
Fi1osofЭтот провайдер сейчас из коробки не поддерживается (просто заморожен), но восстановить не долго, доработаем.
Fi1osofСообщение произвольное, можно даже в кириллице. Но в кириллице одно сообщение — 70 символов, в латинице 140.
Fi1osofПовторюсь, гарантии на доставку смсок по таким каналам нет никакой. Нужны белые каналы.
UPD: Заработала епочта. Вы немного слукавили со стоимостью. Она зависит от суммы пополнения баланса. Вы готовы за раз пополнить на 75 000 рублей, чтобы по 25 копеек смски слать? Не думаю. А на небольших суммах стоимость не сильно отличается.
Размер платежа, руб. Тариф, смс/руб.
от 1 до 999 0,51
от 1 000 0,48
от 2 000 0,43
UPD 2: Vlas, регистрация вчера ради одного коммента. Не рекламы ли ради?
Fi1osofНо этот вроде как не нуждается в оказании поддержки, недавно ставил, все работает (подключал letsads.com/ ).
Выложил пакет в официальный репозиторий, но там еще не опубликовалось. Вот прямая ссылка: modxclub.ru/assets/files/extras/smsgate-1.0.0-beta.transport.zip