Привет, Хабр!
Сегодня мы по шагам расскажем, как подключить проверку пользовательских данных с помощью одноразового пароля по 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
мы создадим пять шаблонов:
signup.html
для ввода номера телефона.start.html
для стартовой страницы.error.html
на случай ввода неверного кода.result.html
для получения страницы с персональными данными.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: