Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
titleconfig/hupo_configuration.default.yml
password_recovery:
  enabled: falsetrue
  cache:
    expiration: 5 # minutes
  resend_interval: 30 # seconds
  phone_prefix: ""
  recovery_code_length: 4 # minimum 2
  script_path: /etc/hydra/hupo/recovery_script.sh
  max_codes_number: 3
  • enabled

    признак

    активности

    восстановления

    пароля.

    Может

    принимать

    значения

    true/false;

  • cache.expiration

    время

    в

    минутах

    в течение

    которого

    хранятся

    данные

    для

    восстановления

    пароля

    (количество

    запрошенных

    кодов

    подтверждения,

    текущий

    код

    подтверждения);

  • resend_interval

    время

    в

    секундах,

    которое

    будет

    ждать

    абонент,

    прежде

    чем

    сможет

    повторно

    отправить

    код

    подтверждения;

  • phone_prefix

    префикс

    телефонного

    номера,

    который

    отображается

    на

    форме

    ввода

    номера

    и

    добавляется

    в

    начало

    номера

    телефона

    для

    поиска

    в

    Гидре

    и

    скрипт

    по

    отправке

    СМС;

  • recovery_code_length

    количество

    цифр

    в

    коде

    подтверждения;

  • script_path

    путь

    к

    скрипту

    для

    отправки

    СМС

    (или

    любого

    другого

    способа

    оповещения

    абонента). ЛК передает в скрипт 3 параметра:

    1. сообщение с кодом подтверждения, например "Код подтверждения 0102", задаётся в locales/ru.yml, ключ password_recovery.recovery_message;

    2. строку с кодом подтверждения, например "0102";
    3. номер телефона, который был использован для поиска абонента в Гидре (без плюса, скобок "(", ")", минусов и пробелов), например 79035301234;
  • max_codes_number

    максимальное

    количество

    отправки

    кодов подтверждения за один цикл восстановления пароля. 

    кодов подтверждения за один цикл восстановления пароля.

Подробное описание

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

Поиск абонента

Процесс начинается с перехода по ссылке "Забыли пароль?" на форме логина. Ссылка показывается только если в конфиге enabled: true.

Image Added

После перехода по ссылке предлагается ввести логин и телефон для поиска абонента в Гидре.

Image Added

На скриншоте у телефона есть префикс: "+7". Префикс задаётся в конфиге в поле phone_prefix в виде строки. Он будет использоваться для поиска телефона в Гидре, для отправки СМС. 

Логин — логин из доступа к приложению ЛК, телефон — включенный основной телефон для уведомлений, привязанный к БСУ.

Перед поиском из номера телефона удаляются круглые скобки, знак плюса, минусы и пробелы. При нашей конфигурации если абонент ввёл текст "(915) - 777 - 88 - 99", то для поиска используется строка "79157778899". Логин не изменяется.

Если абонент подобрался, то мы переходим к следующему шагу, иначе показывается ошибка: "Абонент с такими данными не существует".

Все коды ошибок заданы в locales/ru.yml, ключ password_recovery.errors.

Генерация кода подтверждения

Длина кода подтверждения задаётся в конфиге в recovery_code_length. Код подтверждения генерируется и хранится в виде строки. Это нужно для того, чтобы работали коды вида "0001".

Затем код и другие данные (дата генерации кода, время хранения записи, логин, телефон, счётчик текущего кода подтверждения) сохраняются в кеш. Если необходимо, такие записи можно найти в кеше по ключу с логином. Формат ключа: "recovery_#{login}". В нашем случае сохранится запись с ключом: "recovery_sir_arthur".

Вызов скрипта для отправки сообщения

Путь к скрипту задаётся в конфиге в script_path. Это должен быть скрипт, который принимает 3 параметра - они описаны в разделе с конфигурационным файлом. Предполагается, что в скрипт обращается к внешнему сервису для отправки СМС сообщения на номер абонента.

После вызова скрипта абонент перенаправляется на страницу с вводом кода подтверждения.

Пример скрипта на Python для сервиса SMS-центр (https://smsc.ru):

Code Block
languagepy
titlesend_sms.py
collapsetrue
#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import sys, os, re

login = "SmsCenterLogin"
password = "PassHere"

# Проверка корректности передачи аргументов
if len(sys.argv) < 3:
    os._exit(0)

# Аргументы
phone_number = sys.argv[3]  # Номер телефона
msg = sys.argv[1]           # Сообщение, уже содержит код
code = sys.argv[2]          # Код подтверждения

# Проверка корректности номера телефона
p = re.compile("^\d{11}$")
phone_match = p.match(phone_number)
if not(phone_match) or ((phone_match) and (phone_match.group() != phone_number)):
    os._exit(0)

# Формирование команды с запросом к SMS-центру
cmd = "curl --url \"https://smsc.ru/sys/send.php\" -d " + \
      "\"login=%s&psw=%s&phones=%s&mes=%s&charset=utf-8\"" % \
      (login, password, phone_number, msg)

# Отправка команды через SMS-центр
os.system(cmd)

Вызов скрипта для отправки сообщения внутри docker-контейнера

После переезда HUPO внутрь docker-контейнера чтобы не возиться с pyenv и дополнительными модулями, зачастую проще написать скрипт на bash, если отправка смс сводится к curl запросу. Скрипт должен быть проброшен в docker-compose.yml и быть исполняемым (chmod +x send_sms.sh).

Ниже пример такого скрипта:

Code Block
languagebash
titlesend_sms.sh
collapsetrue
#!/bin/bash
# ВНИМАНИЕ! Проверка отправки смс должна делаться только на определенные номера, которые пропускает СМС-шлюз !
#set -x   - раскомментировать для отладки!
 
# Проверка корректности передачи аргументов
if [ "$#" -ne 3 ]; then
  exit 1
fi

MSG=$1
PIN=$2
PHONE=$3
#PHONE='998933221122' #обрати внимание - номер 12  знакомест, а не 11 как в РФ

DATE=$(date +"%x %T")
LOGFILE=/tmp/password_recovery_hupo.log

PSW='CHANGE_ME'
LGN='CHANGE_ME'
CGPN='CHANGE_ME'
URL='http://sms.com:8088/json2sms' # заменить на свою точку входа

# Проверка корректности номера телефона 
PHONE=`echo "$3" | sed -n '/^[0-9]\{12\}$/p'` #обрати внимание - номер 12  знакомест, а не 11 как в РФ
if [ -z "$PHONE" ]; then
  exit 1
fi

# Формирование команды с запросом к SMS-центру
echo -e | curl --header "Content-Type: application/json" --request POST --data \
"{\"login\":\"$LGN\",\"pwd\":\"$PSW\",\"CgPN\":\"$CGPN\",\"CdPN\":\"$PHONE\",\"text\":\"$MSG\"}" --url $URL -v

echo "$DATE curl --header \"Content-Type: application/json\" --request POST --data \
'{\"login\":\"$LGN\",\"pwd\":\"$PSW\",\"CgPN\":\"$CGPN\",\"CdPN\":\"$PHONE\",\"text\":\"$MSG\"}' --url $URL -v" >> $LOGFILE


Ввод кода подтверждения

Абонент получает код на телефон и вводит его в поле "Код". Если код совпадает с сохраненным в кеше, то абонент переходит на шаг смены пароля. Если код не приходит, то можно отправить повторно с помощью ссылки "Отправить ещё раз". Повторная отправка вызовет генерацию нового кода, вызовет скрипт для отправки СМС и обновит запись в кеше.

Image Added

Для повторной отправки установлен таймаут в секундах, который задаётся в конфиге в resend_interval. Таймер с таймаутом будет работать даже после обновления страницы.

Количество повторных отправок тоже ограничено параметром в конфиге max_codes_number. Если абонент превысит число повторных отправок, то будет выведена ошибка "Превышено число повторных обращений. Обратитесь в контактный центр".

Если абонент ввёл правильный код, то его перебросит на страницу ввода нового пароля.

Ввод нового пароля

Новый пароль нужно вводить дважды. Если пароль в первом инпуте совпадает с паролем во втором инпуте, то пароль меняется.

После сохранения нового пароля запись в кеше удаляется. Запустить восстановление пароля можно ещё раз.

Note

Число таких попыток не ограничено.

После сохранения нового пароля нужно залогиниться в ЛК.

 

Note

Надо понимать, что восстановление пароля и все ограничения (на таймаут, повторную отправку) действуют в течение времени жизни записи в кеше. Это значение задаётся в конфиге в cache.expiration в минутах.