Как настроить аутентификацию через SMS и Flask для самых-самых ленивых пользователей

от автора

Привет, Хабр!

Сегодня мы по шагам расскажем, как подключить проверку пользовательских данных с помощью одноразового пароля по SMS. Для этого будем использовать платформу MTC Exolve и фреймворк Flask. Такой метод легко внедрить в свой проект и сделать работу с простыми личными кабинетами удобной и максимально ненапряжной для пользователей.

Увы, многие пользователи не любят запоминать пароли, но им можно предложить вход по SMS

Часто онлайн-сервисы заменяют стандартную пару из логина и пароля на более удобный способ аутентификации — вход через номер телефона и одноразовый SMS-код. Подробно об этом мы говорили в прошлой статье. Уточним, что для повышения уровня защиты от хакерских и фишинговых атак лучше использовать более сложные механики. Цель фишинговых атак — завладеть личной информацией пользователей: паролями, данными банковских карт. Поэтому придется усложнять доступ к номеру телефона и SMS для злоумышленника. Мы же ограничимся основной схемой аутентификации, которая подойдет для редких и разовых входов в простые личные кабинеты без важных персональных данных. В дальнейшем ее можно использовать и как элемент более сложных способов аутентификации.

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

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

Ниже мы расскажем, как настроить аутентификацию с помощью SMS API от платформы MTC Exolve и фреймворка Flask. В этом примере мы покажем, как отправить одноразовый код на указанный номер телефона. Для этого понадобятся только API-ключ и номер телефона отправителя, который можно приобрести на нашей платформе.

Пример простой реализации отправки SMS с помощью Flask           

Почему Flask? Он неплох для создания легкого примера, предлагает базовый набор инструментов, помогает сразу начать разработку и подходит для создания микросервисов. Если вы знаете только Python и нужна интеграция вашего проекта с другими сервисами, то как раз этот фреймворк подойдет идеально.

Посмотрим, как реализовать отправку кода на телефон пользователя и верификацию через SMS-код для последующей авторизации на примере Flask-приложения.

Для начала убедитесь, что у вас установлен Flask и библиотека requests: pip install Flask requests

Создание структуры

flasksms/     /venv     /templates         signup.html         verify.html    start.html    result.html    error.html     app.py     config.py     dev.env

Создание шаблонов

В директории templates мы создадим пять шаблонов:

  1. signup.html для ввода номера телефона.

  2. start.html для стартовой страницы.

  3. error.html на случай ввода неверного кода.

  4. result.html для получения страницы с персональными данными.

  5. verify.html для ввода полученного SMS-кода.

Вы можете стилизовать эти шаблоны в соответствии с вашим дизайном.                            

Создание приложения

Файл app.py будет содержать логику Flask-приложения.

Дальше создадим маршруты для стартовой страницы, отправки SMS-кода и верификации кода. Кроме того, добавим словарь generated_codes для хранения сгенерированных кодов.

Получим данные из переменных окружения в файл config.py:

from dotenv import dotenv_values  info_env = dotenv_values('dev.env')  API_KEY = info_env.get('API_KEY') PHONE_SEND = info_env.get('PHONE_SEND')

Создадим стартовый маршрут в app.py:

from flask import Flask, render_template, request, jsonify import requests import random import string from config import API_KEY, PHONE_SEND  app = Flask(__name__)   # Секретный ключ приложения app.secret_key = API_KEY  # Номер телефона для отправки кода phone_send = PHONE_SEND   # Словарь для хранения сгенерированных кодов generated_codes = {}  @app.route('/', methods=['GET'])  def start():   return render_template('start.html')

Стартовый шаблон в html сделаем таким:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Добро пожаловать</title> <style> body { background-color: white; font-family: Arial, sans-serif; text-align: center; } h3 { margin-top: 80px; } </style> </head> <body> <h3>Добро пожаловать</h3> <h5>Простое приложение flask для получения персональных данных с помощью одноразового SMS-кода</h5> <p>Для получения персональных данных перейдите по ссылке <a href="http://0.0.0.0:5000/signup">здесь</a>.</p> <p>--------------------------------------------------------------</p> </body> </html> 

Потом создадим маршрут /singup для получения номера телефона:

@app.route('/signup', methods=['GET', 'POST'])  def signup():  if request.method == 'POST': number = request.form['number']   # Генерируем случайную последовательность из 5 латинских букв  code = ''.join(random.choice(string.ascii_letters) for _ in range(5))   # Отправляем SMS сгенерированным кодом  sms_data = { "number": phone_send, "destination": number, "text": code}  headers = {'Authorization': f'Bearer {API_KEY}'}  response = requests.post(url="https://api.exolve.ru/messaging/v1/SendSMS", json=sms_data, headers=headers)  if response.status_code == 200:  # Сохраняем сгенерированный код для дальнейшей проверки  generated_codes[number] = code  return render_template('verify.html', number=number)  else:  return f"Ошибка при отправке SMS: {response.status_code}"   return render_template('signup.html')

Переменную number будем забирать из тега input шаблона signup.html:

<!DOCTYPE html> <html> <head> <title>SMS Signup</title> <style> .container { width: 33.33%; margin: 0 auto; }        label { display: block; } input[type="text"] { width: 70%; padding: 10px; border-radius: 5px; border: 1px solid #ccc; margin-bottom: 10px; } button[type="submit"] { background-color: #7FBB28; color: #fff; border: none; padding: 10px 20px; border-radius: 5px; cursor: pointer; } button[type="submit"]:hover { background-color: #7FСB10; } </style> </head> <body> <div class="container"> <h1>Доступ к данным по SMS</h1> <form method="POST" action="/signup"> <label for="number">Номер мобильного:</label> <input type="text" name="number" placeholder="+7 --- --- -- --" required> <button type="submit">Получить код</button> </form> </div> </body> </html>

Командой requests.post(url="https://api.exolve.ru/messaging/v1/SendSMS", json=sms_data, headers=headers) отсылаем запрос на отправку SMS по номеру, введенному в форму. В заголовках headers указываем тип авторизации и API-ключ приложения.

Если отправка SMS прошла успешно, перебрасываем пользователя на шаблон verify.html.

Теперь создадим маршрут для сверки сгенерированного кода и кода, который ввел пользователь:

@app.route('/verify/<number>', methods=['GET', 'POST'])  def verify(number):  if request.method == 'POST':  entered_code = request.form['code']  if number in generated_codes and entered_code == generated_codes[number]:  pasport = ''.join(str(random.randint(0, 9)) for _ in range(10)) credit = ''.join(str(random.randint(0, 9)) for _ in range(16)) data = {“номер счета”: credit, “номер паспорта”: pasport} return render_template('result.html', data=data)   else:  return render_template('error.html')   return render_template('verify.html', number=number)

Раз мы перебросили пользователя на страницу verify.html, то ее стоит доработать. Ниже стили, которые вы можете исправить по вкусу:

<!DOCTYPE html> <html> <head> <title>Подтверждение</title> <style> .container { width: 33.33%; margin: 0 auto; } label { display: block; }  input[type="text"] { width: 70%; padding: 10px; border-radius: 5px; border: 1px solid #ccc; margin-bottom: 10px; }  button[type="submit"] { background-color: #9eccc1; color: #fff; border: none; padding: 10px 20px; border-radius: 5px; cursor: pointer; }   button[type="submit"]:hover { background-color: #9ec1cc; } </style> </head> <body> <div class="container"> <h1>Подтверждение кода</h1> <form method="POST" action="/verify/{{ number }}"> <label for="code">Введите код:</label> <input type="text" name="code" required> <button type="submit">Подтвердить</button> </form> </div> </body> </html>

Дальше в теге input ожидаем ввод кода и кнопкой button посылаем код на маршрут /verify/<number>. Если код, введенный пользователем, совпадает с сохраненным кодом в словаре generated_codes[number], мы можем отдать данные пользователя. В этом случае для простоты отдаем шаблон result.html, в который кладем случайно сгенерированный номер счета и паспорта.

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

<!DOCTYPE html> <html> <head> <style> table { border-collapse: collapse; margin: 0 auto; } th, td { padding: 10px; text-align: left; } th { background-color: #f2f2f2; border-radius: 10px 10px 0 0; } td { border-bottom: 1px solid #ddd; } </style> </head> <body> <table> <tr> <th>Номер счета</th> <td>{{ data['номер счета'] }}</td> </tr> <tr> <th>Номер паспорта</th> <td>{{ data['номер паспорта'] }}</td> </tr> </table> </body> </html>

Если код неверный, вернем пользователю страницу error.html с ошибкой и предложением попробовать снова:

<!DOCTYPE html> <html> <head> <style> body { text-align: center; font-family: Arial, sans-serif; } .message { margin-top: 100px; font-size: 24px; color: red; } .link { margin-top: 20px; font-size: 16px; text-decoration: none; } </style> </head> <body> <div class="message">Извините, неверный код.</div> <a class="link" href="http://0.0.0.0:5000/signup">Попробуйте снова</a> </body> </html>

В каких еще ситуациях применяется OTP через SMS

  • Двухфакторная аутентификация, про которую писали раньше. Одноразовый код через SMS можно использовать дополнительно к имени пользователя и паролю.

  • Проверка номера телефона. Некоторые службы используют номер телефона в качестве основного идентификатора пользователя. В таких сервисах пользователи могут ввести свой номер телефона и одноразовый пароль, чтобы подтвердить свою личность. Иногда он сочетается с PIN-кодом для двухфакторной аутентификации.

  • Восстановление аккаунта. Если пользователь потерял доступ к своей учетной записи, он может восстановить ее через отправку email или SMS-сообщения.

  • Подтверждение платежа. В платежных системах некоторые банки или эмитенты кредитных карт запрашивают у плательщика дополнительную аутентификацию в целях безопасности. Обычно в таких случаях используют push или SMS с одноразовым кодом.

На этом все, если у вас возникли вопросы по использованию платформы MTS Eхolve, то ждем их в комментариях.


Р. S. Через облачную платформу МТС Exolve можно реализовать разные сценарии общения с клиентами: обратный звонок, кол-трекинг, защиту номера, выбор исходящего номера, SMS-информирование и другие. Что еще можно почитать на Хабре про Exolve:


ссылка на оригинал статьи https://habr.com/ru/articles/829764/


Комментарии

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

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