Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
ASP.NET MVC 5 поддерживает также подтверждение регистрации по sms. Но чтобы включить данную функциональность в приложении, нам надо связать наше приложение с сервисом, который будет отправлять sms через специальный API. Одним из таких сервисов является Twilio
Итак, создадим проект и первым делом подключим через NuGet пакет, который позволит взаимодействовать с этим сервисом:
Теперь надо зарегистрироваться на самом этом сервисе и получить идентификатор аккаунта 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