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
У многих sms-провайдеров жены указаны в районе +-40 копеекДешевые жены у них...
Прости, не удержался — фраза двусмысленной получилась, исправь пожалуйста…
Что включает в себя компонент для работы? Сниппет? Интерфейс в админке?
У многих sms-провайдеров жены указаны в районе +-40 копеекОпечатка по Фрейду))
Дешевые жены у них...
Что включает в себя компонент для работы? Сниппет? Интерфейс в админке?Службу. То есть
$smsGate = $modx->getService("smsGate");
$smsGate->send($phone, $message);
Еще есть таблица в БД, куда складываются отправляемые СМСки и их статусы. Есть метод проверки статуса СМС, при этом ее статус в БД обновляется при запросе. Будут продажи и будут пожелания: будут интерфейсы и прочие плюшки.
Понятно, спасибо, нужная вещь!
Не за что
Создайте у себя плагин на событие OnWebAuthentication и пропишите в нем $modx->event->_output = 'false';False, наверное, без кавычек?
Ночью пытался воспроизвести на чистом MODX 2.5.2 — не удалось.
Именно с кавычками. false без кавычек — это логическое нет, и оно empty(). А вот с кавычками — это строчное 'false' 5 символов, и это не равно empty(). С false без кавычек и не будет работать.
Николай, до меня не доходит. А как туда попадает false в кавычках?
Это просто в плагине прописывается и все. Не обязательно 'false', можно написать 'bla-bla-bla'
Воспроизвести удалось. Но если на то пошло, то имея доступ к запуску процессора и правки плагинов, можно и через MODX API так же авторизовать себя под любым юзером без пароля, в т.ч. и под админом.
Это не стоит расценивать как дыру в безопасности напрямую. Это просто логическая ошибка. И речь не о том, что ей можно воспользоваться для взлома, а о том, что логика не позволяет корректно обрабатывать ошибки. Вот при сохранении документа вы же можете прописать плагин, который в случае чего будет говорить «Документ нельзя сохранить потому-то и потому-то», а вот здесь этого не получается сделать.
Использовал на проекте ТЫЦ: цена приятная, подключение проще простого(создание объекта->аутентификация->отправка). Для моих тривиальных целей он подошел более чем. Я не знаю правда систему работы с Россией(это украинский сервис), но вроде как можно.
letsads.com тоже Украинский, и норм все. Гораздо интересней вопрос сколько у них стоит официальный канал, а не интернетовский, но позже посмотрю детальней. Спасибо!
smsaero.ru пользуемся 2 года. Отличный саппорт, удобное пополнение счета, личный менеджер для юр. лиц. простой и удобный REST API: статусы доставки, запрос баланса, массовая рассылка по списку контактов и т.д. Полная информация об API здесь smsaero.ru/api/description/. Еще могут отсылать в ВотсАп и Вибер.
Из минусов:
Все акции, подарочные сертификаты и т.п. не работают для юр. лиц.
Ребята сидят в Омске, сдвиг рабочего времени +3 ч от Москвы.
Из минусов:
Все акции, подарочные сертификаты и т.п. не работают для юр. лиц.
Ребята сидят в Омске, сдвиг рабочего времени +3 ч от Москвы.
Спасибо! Посмотрю.
На одном из проектов использую digital-direct.ru. API не простое, а совсем примитивное — один GET запрос с необходимыми параметрами. При этом, насколько помню, есть возможность и статусы проверять, и многие другие вещи выполнять.
Спасибо! Гляну.
Кстати, на счет примитивности: тут API тоже не сложное, но важно было еще сохранять в базе смски. Сейчас все попытки отправки записываются в базу данных и можно позже запросить статус, что довольно удобно. Планирую в ближайшее время сделать еще интерфейс произвольной отправки сообщений прям через управление пользователей (как в switchUser сделано «Авторизоваться», так будет «Отправить сообщение» если номер указан). На отдельных проектах вполне может пригодиться такая функция для оперативного уведомления.
Все, компонент опубликован. modstore.pro/packages/alerts-mailing/smsgate
Пожалуй не соглашусь с этими претензиями к MODX.
1. событие «OnWebAuthentication» на самом деле правильнее назвать было бы «OnBeforeWebAuthentication»
и в этой роли оно свой функционал отрабатывает идеально.
У меня, например, сейчас с помощью этого события реализован функционал авторизации по ссылке. Пришла ссылка на email — тыц на нее — и ты уже залогинен.
2. По поводу "$modx->event->_output" вообще претензия странная.
«Я туда сую неверное значение и MODX плохо работает». Так не суйте неверное.
Если в процессе работы плагина выходит, что пользователь достоин авторизации, то делаем
3. Добавить событие «OnAfterWebAuthentication» было бы полезно
1. событие «OnWebAuthentication» на самом деле правильнее назвать было бы «OnBeforeWebAuthentication»
и в этой роли оно свой функционал отрабатывает идеально.
У меня, например, сейчас с помощью этого события реализован функционал авторизации по ссылке. Пришла ссылка на email — тыц на нее — и ты уже залогинен.
2. По поводу "$modx->event->_output" вообще претензия странная.
«Я туда сую неверное значение и MODX плохо работает». Так не суйте неверное.
Если в процессе работы плагина выходит, что пользователь достоин авторизации, то делаем
$modx->event->_output = true;
в иных случаях не трогаем. И все работает как надо.3. Добавить событие «OnAfterWebAuthentication» было бы полезно
2. По поводу "$modx->event->_output" вообще претензия странная.Дмитрий, если вам претензия кажется странной, то это просто потому что опыта пока маловато. Вам просто надо поверить мне на слово, что так не должно быть.
«Я туда сую неверное значение и MODX плохо работает». Так не суйте неверное.
Но плюс к слову, аргументирую.
Вот смотрите, процессор обновления документа расширяет базовый процессор modObjectUpdateProcessor. В этом процессоре есть метод fireBeforeSaveEvent(). Если у текущего процессора есть свойство $this->beforeSaveEvent, то на это событие вызывается плагин. В процессоре обновления документа resource/update это свойство есть, и когда процессор отрабатывается, выполняется и плагин. И в плагине можно вернуть сообщение об ошибке. И на это в базовом процессоре прописан корректный обработчик. Обратите внимание, что в этом обработчике прописано присвоение возвращаемой переменной $preventSave. И внимательно посмотрите на эту конструкцию:
$preventSave = $this->fireBeforeSaveEvent();
if (!empty($preventSave)) {
return $this->failure($preventSave);
}
Если $preventSave не пустое, то возвращается ошибка. Вот это правильная работа плагина. Создайте плагин на событие OnBeforeDocFormSave и пропишите $modx->event->_output = «false»; и попробуйте сохранить документ. Что получите? Ошибку.Вас смущает 'false'? Так вот, это не неверное значение, как вы выразились, а произвольное строчное значение, то есть сообщение. И это сообщение может быть более непрограммиступонятное, и даже можно подсвечивать произвольные поля.
Вот это корректная работа плагина.
А что у нас в security/login прописано? Тупо возврат логического false. Из-за чего корректной обработки не происходит.
У меня, например, сейчас с помощью этого события реализован функционал авторизации по ссылке. Пришла ссылка на email — тыц на нее — и ты уже залогинен.Вы просто выполняете дополнительные действия, никак не влияя на ход выполнения процессора. А вы попробуйте в этом своем плагине вернуть ошибку пользователю и прервать его авторизацию.
Если в процессе работы плагина выходит, что пользователь достоин авторизации, то делаемУ нас с вами разные понятия «как надо». Сделаете вы $modx->event->_output = true; или не сделаете ничего, результат не поменяется в принципе. А вы сделайте так, чтобы поменялся.
в иных случаях не трогаем. И все работает как надо.$modx->event->_output = true;
3. Добавить событие «OnAfterWebAuthentication» было бы полезноА вы поищите хорошенько, может что-то подобное найдете.
Еще раз:
Чушь, что плагин OnAfterWebAuthentication неверно работает и
он сейчас работает для обхода проверки пароля
для того что бы можно было авторизовать пользователя не зная его пароля
ферштейн?
вы же его пытаетесь использовать для другого совершенно. Для запрета авторизации.
такой функционал был бы полезен, слов нет. Но этот плагин не для этого.
поэтому не фикс надо отправлять, а апдейт. Добавить еще одни плагин для нужного вам функционала
Про
Если вы не сделаете ничего, то плагина и нет как бы, и тогда с неверным логин/паролем пользователя не авторизуют
А если сделаете «modx->event->_output = true;» то проверки пароля не будет
и пользователь авторизуется только по логину.
Про
OnWebLogin — не то, в этот момент пользователь уже авторизован, а нужно этого не допустить
Чушь, что плагин OnAfterWebAuthentication неверно работает и
Надеюсь, кто-нибудь отправит багфикс.плагин свою логику отрабатывает на 5+
он сейчас работает для обхода проверки пароля
для того что бы можно было авторизовать пользователя не зная его пароля
ферштейн?
вы же его пытаетесь использовать для другого совершенно. Для запрета авторизации.
такой функционал был бы полезен, слов нет. Но этот плагин не для этого.
поэтому не фикс надо отправлять, а апдейт. Добавить еще одни плагин для нужного вам функционала
Про
Создайте у себя плагин на событие OnWebAuthentication и пропишите в нем $modx->event->_output = 'false';… Как результат: авторизация. joxi.ru/Y2LjLVESn3pqXrи
Сделаете вы $modx->event->_output = true; или не сделаете ничего, результат не поменяется в принципе.Сами себе противоречите )))
Если вы не сделаете ничего, то плагина и нет как бы, и тогда с неверным логин/паролем пользователя не авторизуют
А если сделаете «modx->event->_output = true;» то проверки пароля не будет
и пользователь авторизуется только по логину.
Про
А вы поищите хорошенько, может что-то подобное найдете.
OnWebLogin — не то, в этот момент пользователь уже авторизован, а нужно этого не допустить
он сейчас работает для обхода проверки пароляПообщались с Джейсоном И Марком, отправил PR github.com/modxcms/revolution/pull/13204
для того что бы можно было авторизовать пользователя не зная его пароля
ферштейн?
Если примут, то можно будет не только разрешать авторизацию без пароля (если возвращать true), но и можно будет выбрасывать собственные ошибки. Так будет гораздо гораздее.
OnWebLogin — не то, в этот момент пользователь уже авторизован, а нужно этого не допустить
Как раз этого и хотел не допустить, и это и решает данный PR. Его неидеальность только в том, что придется в нем в случае чего все равно проверять пароль, если надо проверить пароль (так как сейчас проверка пароля идет уже за пределами вызова этого события), но это не страшно. Теперь, если вы считаете, что все проверки пройдены, но не надо позволить пользователю авторизоваться, можно будет просто вернуть сообщение ошибки (не true и не false).
код бы свой проверили сначала что ли
он конечно безобидный, в том смысле что никогда не выполнится )))
но полезнее, если работать будет:
вместо
if ($rt && (is_array($rt) && !in_array(true, $rt)))
надо
if ($rt && is_array($rt) && !in_array(true, $rt, true))
ps Изящно исправили. аж восхитился. Серьезно!
он конечно безобидный, в том смысле что никогда не выполнится )))
но полезнее, если работать будет:
вместо
if ($rt && (is_array($rt) && !in_array(true, $rt)))
надо
if ($rt && is_array($rt) && !in_array(true, $rt, true))
ps Изящно исправили. аж восхитился. Серьезно!
Спасибо, поправил. Проверял, но видимо к вечеру глаз замылился.
Какие-то цены зверские на смс.
Может есть способ отправлять смс посредством обычной связи.
Есть же GSM модули всякие.
Может есть способ отправлять смс посредством обычной связи.
Есть же GSM модули всякие.
Возможно ли использовать данное решение в купе с AjaxForm + Formit, только вместо оправки формы на e-mail, осуществлялась отправка данных формы на номер администратора сайта по смс?
Хук для Formit, там вызываете сервис smsgate и шлете куда угодно.
В хуке доступны все поля формы.
В хуке доступны все поля формы.
Все верно, все делается через хуки.
И как было заявлено в описании компонента, с нашей стороны помощь в настройке. Так что если не справитесь самостоятельно, поможем.
И как было заявлено в описании компонента, с нашей стороны помощь в настройке. Так что если не справитесь самостоятельно, поможем.
Это было бы здорово, куда пройти за помощью?) Чтобы ветку не захламлять
Приобретайте пакет в модсторе и пишите там же в поддержку. Я на связи сегодня.
Отлично. Дело не сегодняшнего дня, но на следующей неделе обязательно это дело нужно закончить
Не вопрос.
Николай, еще один «глупый» вопрос: какими сервисами можно пользоваться для отправки смс, важно для определения конечной стоимости для клиента.
Про сервисы я писал в статье. Сейчас компонент работает с letsads.com/ (хотя будет позже реализация работы с различными провайдерами, и сразу будет реанимирован iqsms.ru/).
Белые смс-ки на летсадс стоят 1.70. Это средняя по рынку стоимость.
Белые смс-ки на летсадс стоят 1.70. Это средняя по рынку стоимость.
тут тонкий момент, заказчик юридическое лицо и сильно переживает за тонкости юридические при взаиморасчетах с иностранными контрагентами
Ну iqsms.ru тогда в помощь. Но там на белом канале по-моему от 5000 платеж минимальный, и смс 1.99 на белом канале.
Этот провайдер сейчас из коробки не поддерживается (просто заморожен), но восстановить не долго, доработаем.
Этот провайдер сейчас из коробки не поддерживается (просто заморожен), но восстановить не долго, доработаем.
А компонент может отправлять смс с нужным мне текстом, а не только паролем? К примеру, остаток на счету
Да, как я и писал выше. Просто в любом месте:
$smsGate = $modx->getService(«smsGate»);Сообщение произвольное, можно даже в кириллице. Но в кириллице одно сообщение — 70 символов, в латинице 140.
$smsGate->send($phone, $message);
Кстати не на всех сервисах для массовой смс рассылки цена где-то в пределах 40 копеек, к примеру на этом — https://www.epochta.com.ua/products/sms/ 25 копеек за сообщение, да и если сильно потрудиться, то думаю еще дешевле можно найти
Епочта немного висит joxi.ru/DmBXep0uwNJJ9A
Повторюсь, гарантии на доставку смсок по таким каналам нет никакой. Нужны белые каналы.
UPD: Заработала епочта. Вы немного слукавили со стоимостью. Она зависит от суммы пополнения баланса. Вы готовы за раз пополнить на 75 000 рублей, чтобы по 25 копеек смски слать? Не думаю. А на небольших суммах стоимость не сильно отличается.
Размер платежа, руб. Тариф, смс/руб.
от 1 до 999 0,51
от 1 000 0,48
от 2 000 0,43
UPD 2: Vlas, регистрация вчера ради одного коммента. Не рекламы ли ради?
Повторюсь, гарантии на доставку смсок по таким каналам нет никакой. Нужны белые каналы.
UPD: Заработала епочта. Вы немного слукавили со стоимостью. Она зависит от суммы пополнения баланса. Вы готовы за раз пополнить на 75 000 рублей, чтобы по 25 копеек смски слать? Не думаю. А на небольших суммах стоимость не сильно отличается.
Размер платежа, руб. Тариф, смс/руб.
от 1 до 999 0,51
от 1 000 0,48
от 2 000 0,43
UPD 2: Vlas, регистрация вчера ради одного коммента. Не рекламы ли ради?
Николай, компонент прекратил свое существование?
Сергей, все компоненты были сняты с публикации modx.pro/news/12550/
Но этот вроде как не нуждается в оказании поддержки, недавно ставил, все работает (подключал letsads.com/ ).
Выложил пакет в официальный репозиторий, но там еще не опубликовалось. Вот прямая ссылка: modxclub.ru/assets/files/extras/smsgate-1.0.0-beta.transport.zip
Но этот вроде как не нуждается в оказании поддержки, недавно ставил, все работает (подключал letsads.com/ ).
Выложил пакет в официальный репозиторий, но там еще не опубликовалось. Вот прямая ссылка: modxclub.ru/assets/files/extras/smsgate-1.0.0-beta.transport.zip
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.