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

Меня зовут Анастасия Иванова, и я занимаюсь технической документацией в компании  i-Digital. В данной статье я расскажу о том, как можно интегрировать форму для верификации мобильного номера на вашем веб-сайте, используя наш виджет.

Виджет верификации телефона от i-digital direct снимает с вас необходимость самостоятельно отправлять код подтверждения на мобильный номер пользователей, сверять отправленный и введенный код, следить за длительностью сессии и заботиться о безопасности отправки кода. Для использования вам понадобится сделать простую интеграцию в HTML-коде, а также настроить закрытое взаимодействие между серверной частью вашего приложения и сервером i-digital direct. 

Что понадобится

Прежде всего зарегистрируйтесь в Личном кабинете i-digital direct. После регистрации настройте виджет подтверждения телефона и создайте API-ключ для управления им. Для этого следуйте подробным инструкциям из статьи «Настройка виджета в личном кабинете».

В этой статье мы реализуем сервер приложения на NodeJS на базе фреймворка Express. Мы также установим дополнительные модули: body-parser для обработки данных из входящих HTTP-запросов, библиотека axios для осуществления исходящих HTTP-запросов и шаблонизатор nunjucks для JavaScript.

Инициализация приложения и установка зависимостей

Прежде чем приступить к работе, удостоверьтесь, что Node.js установлен на вашем компьютере. Node.js можно загрузить с официального сайта. В комплекте с Node.js поставляется менеджер пакетов npm, который предназначен для установки дополнительных модулей.

Запустите команду npm init в терминале, чтобы создать новый NodeJS проект. Опционально заполните параметры вашего приложения, которые запросит система (наименование, краткое описание, данные автора и прочее). 

Завершение процедуры приведет к формированию конфигураци package.json в вашем проекте, в котором собрана вся указанная информация о вашем приложении (введенная в процессе инициализации) и перечень установленных пакетов.

Добавьте в ваш проект библиотеки, обозначенных в разделе «Что понадобится», выполнив в терминале:

npm install -s express axios body-parser nunjucks

По завершении процесса установки библиотек в файле package.json будет отражен список установленных зависимостей:

Разработка сервера Express.js

Создайте базовое приложение «Hello World», используя Express. Инструкции по его созданию вы найдете на официальном сайте Express.

Включите в ваш проект ранее установленные модули:

// Подключение модулей
const bodyParser = require("body-parser");
const axios = require('axios');
const nunjucks = require('nunjucks');

Настройте приложение на обработку входящих HTTP-запросов с помощью body-parser следующим образом:

app.use(bodyParser.json());
app.use(bodyParser.urlencoded( {extended: false} ))

Запустите приложение, используя команду node {file_name}.js в терминале. После старта вы увидите уведомление о работе приложения на указанном вами порту в терминале. Перейдите по адресу http://localhost:{port}/, чтобы увидеть приветственное сообщение от приложения:

Настройка клиента

Мы будем хранить страницы клиента в отдельной папке views. Создайте соответствующую папку в директории проекта. Создайте в новой папке следующие HTML файлы:

  • index - домашняя страница, на которой пользователь указывает свой мобильный номер;

  • widget - страница с виджетом подтверждения номера от i-digital direct;

  • success - финальная страница с сообщением об успешном прохождении проверки номера.

Структура приложения получится следующей:

Далее мы пошагово рассмотрим реализацию клиентской и серверной частей приложения.

Реализация приложения

Клиент: домашняя страница — index.html

Добавьте на домашнюю страницу элементы form и input для ввода номера мобильного и кнопку (button), которая инициирует POST-запрос с введенным номером на URL /sendPhoneNumber сервера. После получения номера сервер использует его при рендере страницы с виджетом подтверждения номера.

Вставьте HTML-код ниже в файл index.html:

<!-- Форма для ввода номера телефона и отправки POST-запроса на точку доступа сервера /sendPhoneNumber -->
<form method="post" action="sendPhoneNumber">
  <label>Номер мобильного телефона в формате 79*********</label><br /><br />
  <input name="phoneNumber" type="tel" />
  <button>Подтвердить номер телефона</button>
</form>

Сервер: обработка запроса к домашней странице

Укажите использование шаблонизатора nunjucks для отображения HTML-страниц из директории views, которую мы создали на предыдущем шаге. Напишите в файл index.js сервера следующую строчку кода:

nunjucks.configure('views', { express: app });

Адаптируйте обработчик app.get для домашней страницы:

// Настройка ответа на запросы к домашней странице (рендер index.html файла)
app.get('/', (req, res) => {
  res.render('index.html');
});

Таким образом сервер отобразит содержимое index.html при посещении домашней страницы.

Запустите сервер и перейдите по адресу http://localhost:{port}/, чтобы проверить появление формы ввода номера мобильного телефона на домашней странице.

Сервер: обработка данных из формы с номером

Когда пользователь введет номер и нажмет кнопку "Подтвердить", форма отправит POST-запрос по адресу /sendPhoneNumber. Сервер примет этот запрос и покажет страницу с виджетом widget.html со значением номера телефона, введенном на домашней странице. Добавьте следующие строки в index.js:

app.post('/sendPhoneNumber', (req, res) => {
  const phoneNumber = req.body.phoneNumber; // номер телефона формы
  res.render('widget.html', {
    phoneNumber: phoneNumber,
  }); // передаем номер на страницу с виджетом
});

Клиент: страница виджета подтверждения номера — widget.html

На этой странице будет размещаться виджет i-Digital Direct. Для этого в первую очередь подключите в <head> страницы css и js-файлы из CDN i-Digital:

<link rel="stylesheet" href="https://cdn.direct.i-dgtl.ru/VerifyWidget.css" />
<script src="https://cdn.direct.i-dgtl.ru/VerifyWidget.umd.min.js"></script>

Добавьте DOM-элемент, в который будет встраиваться виджет по его id:

<div id="widget"></div>

Далее нужно инициализировать виджет с помощью следующего шаблона кода:

window.VerifyWidget.mount('#ELEMENT_ID', {
   destination: 'CLIENT_PHONE_NUMBER',
   widgetId: 'YOUR_WIDGET_ID',
   captchaSiteKey: 'YOUR_CAPTCHA_SITEKEY'
}, sendAuthKeyFunc, onSuccessFunc)

Описание параметров вы можете посмотреть в нашей статье ”Подтверждение телефона на своем сайте”. Замените следующие значения параметров в шаблоне:

  • ELEMENT_ID - id элемента, который создали выше (widget).

  • CLIENT_PHONE_NUMBER - переменная, в которую подставляется номер, который пользователь ввел на предыдущей странице.

  • YOUR_WIDGET_ID - id виджета, который вы получите после его создания по этой инструкции

  • YOUR_CAPTCHA_SITEKEY - секретный ключ сервиса капчи, который вы получите после ее создания. Подробную инструкцию можно найти в статье “Использование captcha”.

Код инициализации виджета получается такой:

window.VerifyWidget.mount('#widget', {
    destination: '{{ phoneNumber }}', // в переменную phoneNumber подставится номер пользователя
    widgetId: 'widget_id',
    captchaSiteKey: 'captcha_site_key',
  }, sendAuthKeyFunc, onSuccessFunc );

Теперь нужно реализовать коллбэк функции sendAuthKeyFunc и onSuccessFunc.

Когда пользователь выбирает желаемый способ получения кода подтверждения, виджет выполняет функцию sendAuthKeyFunc, в которой передает уникальный идентификатор для отправки кода (key). Вам нужно передать этот идентификатор на серверную часть своего приложения.

Для этого добавьте fetch запрос к адресу /sendAuthKeyFunc, который передаст key при вызове sendAuthKeyFunc:

const sendAuthKeyFunc = (key) => {
   const payload = {
     key,
   };
   return fetch('/sendAuthKeyFunc', {
     method: 'POST',
     headers: {
       'Content-Type': 'application/json',
     },
     body: JSON.stringify(payload),
   });
 };

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

Идентификатор key не передается в функцию onSuccessFunc, как в случае с функцией sendAuthKeyFunc. Чтобы передать значение key при выполнении onSuccessFunc, вы можете заранее создать переменную и прописать в ней значение key при выполнении функции sendAuthKeyFunc. Например:

messageKey = ''; // переменная для будущего сохранение значения key

const sendAuthKeyFunc = (key) => {
  messageKey = key;
  // здесь функция отправки POST-запроса на серверную часть
};

Чтобы передать key на серверную часть приложения при выполнении функции onSuccessFunc, в функцию нужно добавить fetch запрос к адресу /checkVerification. 

После выполнения запроса, клиент должен получить от сервера результат проверки. Если статус проверки будет подтвержден (CONFIRMED), то приложение может показать пользователю страницы, доступные после подтверждения. Так как клиенту необходимо ждать ответ от сервера после fetch запроса, прежде чем показывать скрытые страницы, напишите асинхронную функцию: 

 const onSuccessFunc = async () => {
  const payload = {
    key: messageKey,
  };
   
  // Отправляем POST-запрос на сервер и ждем, пока ответ не запишется в переменную response
  const response = await fetch('/checkVerification', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
    },
    body: JSON.stringify(payload),
  });

  // Преобразовывает ответ от сервера в JSON формат
  const verificationInfo = await response.json();

  // Проверяем, что статус проверки кода подтвержден, убираем      виджет и показываем сраницу успешного подтверждения
  if (verificationInfo.status == 'CONFIRMED') {
    window.VerifyWidget.unmount('widget');
    window.location = '/success';
  }
 };

Код инициализации виджета и функции можно писать в отдельных файлах и импортировать в widget.html файл. Но для простоты реализации, JavaScript код мы будем писать под HTML кодом в теге <script>. Полный код страницы widget.html получается такой:

Hidden text
<link rel="stylesheet" href="https://cdn.direct.i-dgtl.ru/VerifyWidget.css" />
<script src="https://cdn.direct.i-dgtl.ru/VerifyWidget.umd.min.js"></script>

<div id="widget"></div>

<script>
  messageKey = '';
  const sendAuthKeyFunc = (key) => {
    const payload = {
      key,
    };
    messageKey = key;
    return fetch('/sendAuthKeyFunc', {
      method: 'POST'
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(payload),
    });
  };

  const onSuccessFunc = async () => {
    const payload = {
      key: messageKey,
    };

    // Отправляем POST-запрос на сервер и ждем, пока ответ не запишется в переменную response
    const response = await fetch('/checkVerification', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(payload),
    });

    // Преобразовывает ответ от сервера в JSON формат
    const verificationInfo = await response.json();

    // Проверяем, что статус проверки кода подтвержден, убираем виджет и показываем сраницу успешного подтверждения
    if (verificationInfo.status == 'CONFIRMED]') {
      window.VerifyWidget.unmount('widget');
      window.location = '/success';
    }
  };

  window.VerifyWidget.mount(
    '#widget',
    {
     destination: '{{ phoneNumber }}', // в переменную phoneNumber подставится номер пользователя
     widgetId: 'widget_id',
     captchaSiteKey: 'captcha_site_key',
    },

    sendAuthKeyFunc,
    onSuccessFunc
  );
</script>

После рендера страницы с виджетом, пользователь увидит форму виджета с выбором способов подтверждения:

Сервер: обработка запроса на отправку кода подтверждения

При выполнении функции sendAuthKeyFunc на клиенте, ваш сервер получит POST-запрос с идентификатором key для отправки кода подтверждения пользователю. Ваша серверная часть должна ответить 200 OK статусом на этот запрос, чтобы виджет начал проверку отправки кода подтверждения и показал пользователю форму для ввода кода.

Ваш сервер должен сделать запрос к серверу i-digital direct на URL https://direct.i-dgtl.ru/api/v1/verifier/widget/send с полученным от клиента идентификатором, чтобы инициировать отправку кода пользователю. Выполните запрос с помощью библиотеки axios в index.js файле:

app.post('/sendAuthKeyFunc', (req, res) => {
  res.sendStatus(200);
  axios({
    method: 'post',
    headers: { Authorization: 'Basic YOU_API_KEY' },
    url: 'https://direct.i-dgtl.ru/api/v1/verifier/widget/send',
    data: {
      key: req.body.key,
    },
  }).then((response) => {
    console.log(response.data);
  });
});

В ответе от сервера i-digital direct вы получите messageUuid отправленного сообщения. При необходимости вы можете получить полную информацию об отправленном сообщении с помощью метода получения сообщения по id

Сервер: обработка запроса на проверку подтверждения

При выполнении функции onSuccessFunc клиент отправляет идентификатор key на проверку. Ваш сервер должен сделать запрос к серверу i-Digital Direct на URL https://direct.i-dgtl.ru/api/v1/verifier/widget/check с тем же идентификаторов key, чтобы проверить валидность подтверждения номера. После получения ответа о подтверждении отправки кода, отправьте ответ на клиент. Если статус подтверждения CONFIRMED, клиент покажет пользователю страницы скрытые от неавторизованных пользователей.

Добавьте следующую функцию в index.js файл:

app.post('/checkVerification', (req, res) => {
  axios({
    method: 'post',
    headers: { Authorization: 'Basic YOU_API_KEY' },
    url: 'https://direct.i-dgtl.ru/api/v1/verifier/widget/check',
    data: {
      key: req.body.key,
    },
  }).then((response) => {
    res.send(response.data);
  });
});

Клиент: cтраница успешного подтверждения номера — success.html

После успешного ввода кода подтверждения и проверки ваше приложение должно предоставить пользователю доступ к страницам приложения, которые скрыты без авторизации. Для простоты тестирования, создайте простую страницу, которая будет отображаться после проверки кода подтверждения. Добавьте в файл success.html следующий код:

<h1>Авторизация прошла успешно!</h1>

Вывод

Итак мы реализовали форму подтверждения номера телефона на своем сайте с помощью виджета i-digital direct. Запустите проект, чтобы проверить, как все работает:

 

Полный код примера вы можете найти на GitHub.

Комментарии (1)


  1. Daniel217D
    22.06.2024 10:27

    Стоило вынести упоминание виджета в заголовок