Подтверждение телефона по SMS в ASP.NET Identity 2.0

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core

Последнее обновление: 02.12.2015

ASP.NET MVC 5 поддерживает также подтверждение регистрации по sms. Но чтобы включить данную функциональность в приложении, нам надо связать наше приложение с сервисом, который будет отправлять sms через специальный API. Одним из таких сервисов является Twilio

Итак, создадим проект и первым делом подключим через NuGet пакет, который позволит взаимодействовать с этим сервисом:

Twilio в ASP.NET MVC 5

Теперь надо зарегистрироваться на самом этом сервисе и получить идентификатор аккаунта ACCOUNT SID, токен AUTH TOKEN и привязанный к приложению номер телефона, с которого будут отправляться sms.

Значения ACCOUNT SID и AUTH TOKEN можно найти в личном кабинете:

Через пункт меню Numbers можно увидеть номер телефона, привязанный к аккаунту:

Также нам потребуется подключить все те страны, с телефонными кодами которых мы будем взаимодействовать. Это можно сделать в личном кабинете в меню Geographic Permissions на вкладке Messaging. Здесь нам надо отметить все необходимые страны:

После создания учетной записи в Twilio первым делом подключим этот сервис к себе в приложение. Для этого перейдем в файл IdentityConfig.cs, который располагается в папке App_Start. В нем уже приготовлен специальный класс для отправки sms, но пока он по сути ничего не делает:

public class SmsService : IIdentityMessageService
{
    public Task SendAsync(IdentityMessage message)
    {
        // Plug in your sms service here to send a text message.
        return Task.FromResult(0);
    }
}

Там же в файле в методе Create происходит установка этого сервиса для менеджера учетных записей: manager.SmsService = new SmsService();

И теперь подключим в начало файла функциональность twilio: using Twilio; и изменим код сервиса следующим образом:

public class SmsService : IIdentityMessageService
{
    public Task SendAsync(IdentityMessage message)
    {
        string AccountSid = "AC60671f39f9c1edd419022c8f0f9efe9e";

        string AuthToken = "f62e1374032b4b2838d07f085b678d15";

        string twilioPhoneNumber = "+13095884640";

        var twilio = new TwilioRestClient(AccountSid, AuthToken);
		twilio.SendMessage(twilioPhoneNumber, message.Destination, message.Body);

        return Task.FromResult(0);
}

Переменная AccountSid будет хранить идентификатор вашего аккаунта ACCOUNT SID, переменная AuthToken содержит токен AUTH TOKEN, а twilioPhoneNumber - номер телефона, привязанного к вашему аккаунту. В данном случае все эти значения из моего аккаунта, для вашего аккаунта Twilio они будут отличаться.

Теперь надо создать инфраструктуру для отправки sms и верификации полученных через sms кодов.

Модель пользователя ApplicationUser уже имеет свойство PhoneNumber, которое представляет телефон пользователя, а также свойство PhoneNumberConfirmed, указывающее, был ли подтвержден номер телефона. Однако напрямую с этими свойствами при подтверждении мы не будем взаимодействовать, а будем обращаться через специальные методы. Для этого перейдем к контроллеру ManageController. Он уже имеет две пары методов, которые нам понадобятся для работы. Во-первых, метод AddPhoneNumber, который принимает номер телефона и отправляет на него код:

public ActionResult AddPhoneNumber()
{
    return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> AddPhoneNumber(AddPhoneNumberViewModel model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }
    var code = await UserManager.GenerateChangePhoneNumberTokenAsync(User.Identity.GetUserId(), model.Number);
    if (UserManager.SmsService != null)
    {
        var message = new IdentityMessage
        {
            Destination = model.Number,
            Body = "Your security code is: " + code
        };
        await UserManager.SmsService.SendAsync(message);
    }
    return RedirectToAction("VerifyPhoneNumber", new { PhoneNumber = model.Number });
}

Во-вторых, это метод VerifyPhoneNumber, который верифицирует код:

public async Task<ActionResult> VerifyPhoneNumber(string phoneNumber)
{
    var code = await UserManager.GenerateChangePhoneNumberTokenAsync(User.Identity.GetUserId(), phoneNumber);
    return phoneNumber == null ? View("Error") : View(new VerifyPhoneNumberViewModel { PhoneNumber = phoneNumber });
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> VerifyPhoneNumber(VerifyPhoneNumberViewModel model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }
    var result = await UserManager.ChangePhoneNumberAsync(User.Identity.GetUserId(), model.PhoneNumber, model.Code);
    if (result.Succeeded)
    {
        var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
        if (user != null)
        {
            await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
        }
        return RedirectToAction("Index", new { Message = ManageMessageId.AddPhoneSuccess });
    }
    ModelState.AddModelError("", "Failed to verify phone");
    return View(model);
}

Метод AddPhoneNumber в GET-версии возвращает представление, которое предназначено для ввода телефона. А POST-версия метода принимает введенный номер в виде модели AddPhoneNumberViewModel и на основе этого номера генерирует код: var code = await UserManager.GenerateChangePhoneNumberTokenAsync(User.Identity.GetUserId(), model.Number);

Затем формируется сообщение: var message = new IdentityMessage { Destination = model.Number, Body = "Your security code is: " + code};. Это сообщение отправляется await UserManager.SmsService.SendAsync(message);, а фактически передается вышеопределенному классу SmsService для непосредственной отправки.

После этого пользователь перенаправляется на страницу ввода кода, а на телефон пользователя приходит код. После ввода кода данные обрабатываются post-методом VerifyPhoneNumber, в котором с помощью вызова var result = await UserManager.ChangePhoneNumberAsync(User.Identity.GetUserId(), model.PhoneNumber, model.Code); введенный код сравнивается с токеном из бд. Если сравнение прошло успешно, то result.Succeeded возвратит значение true

Для данных методов в файле ManageViewModels.cs уже определены все необходимые модели:

public class AddPhoneNumberViewModel
{
    [Required]
    [Phone]
    [Display(Name = "Phone Number")]
    public string Number { get; set; }
}

public class VerifyPhoneNumberViewModel
{
    [Required]
    [Display(Name = "Code")]
    public string Code { get; set; }

    [Required]
    [Phone]
    [Display(Name = "Phone Number")]
    public string PhoneNumber { get; set; }
}

А в папке Views/Manage уже имеются представления AddPhoneNumber.cshtml и VerufyPhoneNumber.cs.

Запустим приложение, зарегистрируемся и перейдем к добавлению номера по ссылке Manage/AddPhoneNumber:

Номер вводится с плюсиком, например, +79262221133.

После ввода номера мы получим смс на телефон следующего вида:

Введем полученный код:

И после успешной проверки нам отобразится соответствующая страница:

И все, мы прошли проверку. Теперь в базе данных для данного пользователя в поле PhoneNumber будет значится номер телефона, и в программе мы его сможем получить и использовать: user.PhoneNumber

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850