Подтверждение аккаунта и восстановление пароля

Rick Anderson

В этой статье я расскажу вам, как создать ASP.NET Core веб сайт с подтверждением имейла и сбросом пароля.

Создание нового ASP.NET Core проекта

Примечание

Нам потребуется Visual Studio 2015 2 и ASP.NET Core RC2 или выше.

  • В Visual Studio создайте New Project (со Start Page или через File > New > Project)
../../_images/new-project1.png
  • Нажмите Web Application и установите Authentication на Individual User Accounts
../../_images/select-project.png

Запустите приложение, а затем нажмите на ссылку Register и зарегистрируйте пользователя. На данном этапе единственной валидацией является валидация с помощью атрибута [EmailAddress]. После регистрации вы залогинены на сайте.

В SQL Server Object Explorer (SSOX) перейдите к (localdb)MSSQLLocalDB(SQL Server 12). Кликните правой клавишей мышки по dbo.AspNetUsers > View Data:

../../_images/ssox.png ../../_images/au.png

Обратите внимание, что EmailConfirmed установлено на False.

Кликните правой клавишей мышки по строке и из контекстного меню выберите Delete. Далее вы снова будете использовать этот имейл при его подтверждении. Удаление имейла на данном этапе упростит нам дальнейшие шаги.

SSL

Теперь мы настроим проект, чтобы здесь использовался SSL.

Включение SSL в Visual Studio

  • В solution explorer кликните правой клавишей мышки по проекту и выберите Properties
  • Слева нажмите Debug
  • Выберите Enable SSL
  • Скопируйте SSL URL и вставьте его в App URL
../../_images/ssl.png

-Добавьте следующий код в ConfigureServices в Startup:

services.Configure<MvcOptions>(options =>
{
    options.Filters.Add(new RequireHttpsAttribute ());
});

Добавьте в каждый контроллер атрибут [RequireHttps]. Атрибут [RequireHttps] будет перенаправлять все HTTP GET запросы на HTTPS GET и будет сбрасывать все HTTP POST запросы. В целях безопасности лучше всего использовать HTTPS.

[RequireHttps]
public class HomeController : Controller

Подтверждение имейла

Лучше всего подтверждать регистрацию с помощью имейла. Допустим, у вас есть форум, и вы не хотите, чтобы “bob@example.com” зарегистрировался как “joe@contoso.com”. Без подтверждения имейла “joe@contoso.com” можно зарегистрировать в вашем приложении. Предположим, Боб случайно зарегистрировался как “bib@example.com” и не заметил этого, он не смог бы использовать восстановление пароля, поскольку указан неверный имейл. Подтверждение имейла защищает только от ботов, но не защищает от спаммеров со множеством имейлов.

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

Настройка имейл провайдера

Мы будем использовать паттерн опций, чтобы получить доступ к аккаунту пользователя и ключевым настройкам. См. configuration.

  • Создайте класс, соответствующий секретному ключу имейла. В данном примере создан класс AuthMessageSenderOptions в файле Services/AuthMessageSenderOptions.cs.
[RequireHttps]
public class HomeController : Controller
{
    public IActionResult Index()

Настройте SendGridUser и SendGridKey с помощью secret-manager tool. Например:

C:\WebApplication3\src\WebApplication3>dotnet user-secrets set SendGridUser RickAndMSFT
info: Successfully saved SendGridUser = RickAndMSFT to the secret store.

В Windows Secret Manager сохраняет пары ключ/значение в файле secrets.json в директории %APPDATA%/Microsoft/UserSecrets/<userSecretsId>. Директорию userSecretsId можно найти в файле project.json. Вот несколько первых строк файла project.json для этого примера:

{
  "webroot": "wwwroot",
  "userSecretsId": "aspnet-WebApplication3-f1645c1b-3962-4e7f-99b2-4fb292b6dade",
  "version": "1.0.0-*",

  "dependencies": {

В данный момент контекст secrets.json на закодирован. Файл secrets.json показан ниже.

{
  "SendGridUser": "RickAndMSFT",
  "SendGridKey": "",
  "Authentication:Facebook:AppId": "",
  "Authentication:Facebook:AppSecret": ""
}

Использование AuthMessageSenderOptions

Добавьте AuthMessageSenderOptions в контейнер в конце метода ConfigureServices класса Startup.cs:

mports": [
"portable-net45+win8+dnxcore50",
"portable-net45+win8"

Настройка класса AuthMessageSender

Здесь показано, как добавить имейл нотификацию с помощью SendGrid, но вы можете отправлять имейл, используя SMTP или другие механизмы.

  • Установите пакет SendGrid.NetCore NuGet. Из консоли Package Manager введите следующую команду:

Примечание

Пакет SendGrid.NetCore является предварительной версией. Чтобы установить его, нужно использовать опцию -Pre для Install-Package.

. literalinclude:: accconfirm/sample/WebApplication3/src/WebApplication3/Services/MessageServices.cs
language:c#
lines:13-53
dedent:4

Подтверждение аккаунта и восстановление пароля

В шаблоне уже есть код для подтверждения аккаунта и восстановления пароля. Вот как включить этот функционал:

  • Найдите метод [HttpPost] Register в файле AccountController.cs.
  • Снимите комментарий с кода, который включает подтверждение аккаунта.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
{
    ViewData["ReturnUrl"] = returnUrl;
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
        var result = await _userManager.CreateAsync(user, model.Password);
        if (result.Succeeded)
        {
            // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
            // Send an email with this link
            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
            await _emailSender.SendEmailAsync(model.Email, "Confirm your account",
                $"Please confirm your account by clicking this link: <a href='{callbackUrl}'>link</a>");
            //await _signInManager.SignInAsync(user, isPersistent: false);
            _logger.LogInformation(3, "User created a new account with password.");
            return RedirectToLocal(returnUrl);
            
        }
        AddErrors(result);
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

Note: Также мы не даем новому пользователю автоматически залогиниться, закомментировав следующую строку:

//await _signInManager.SignInAsync(user, isPersistent: false);
  • Включите восстановление пароля, сняв комментарий с кода в методе действия ForgotPassword файла Controllers/AccountController.cs.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = await _userManager.FindByNameAsync(model.Email);
        if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
        {
            // Don't reveal that the user does not exist or is not confirmed
            return View("ForgotPasswordConfirmation");
        }

        // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
        // Send an email with this link
        var code = await _userManager.GeneratePasswordResetTokenAsync(user);
        var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
        await _emailSender.SendEmailAsync(model.Email, "Reset Password",
           $"Please reset your password by clicking here: <a href='{callbackUrl}'>link</a>");
        return View("ForgotPasswordConfirmation");
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

Снимите комментарий с кода в ForgotPassword в файле Views/Account/ForgotPassword.cshtml.

@model ForgotPasswordViewModel
@{
    ViewData["Title"] = "Forgot your password?";
}

<h2>@ViewData["Title"]</h2>
<p>
    For more information on how to enable reset password please see this <a href="http://go.microsoft.com/fwlink/?LinkID=532713">article</a>.
</p>

<form asp-controller="Account" asp-action="ForgotPassword" method="post" class="form-horizontal">
    <h4>Enter your email.</h4>
    <hr />
    <div asp-validation-summary="All" class="text-danger"></div>
    <div class="form-group">
        <label asp-for="Email" class="col-md-2 control-label"></label>
        <div class="col-md-10">
            <input asp-for="Email" class="form-control" />
            <span asp-validation-for="Email" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <button type="submit" class="btn btn-default">Submit</button>
        </div>
    </div>
</form>

@section Scripts {
    @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}

Регистрация, подтверждение аккаунта и сброс пароля

  • Запустите приложение и зарегистрируйте нового пользователя.
../../_images/loginaccconfirm1.png
  • Проверьте имейл на наличие ссылки с подтверждением. Если подтверждения нет:

    • Проверьте веб сайт SendGrid, чтобы проверить, отправили ли вы сообщение.
    • Проверьте папку со спамом.
    • Проверьте имейлы на других провайдерах (Microsoft, Yahoo, Gmail и тд.)
    • В SSOX перейдите к dbo.AspNetUsers удалите запись с имейлом и попробуйте еще раз.
  • Нажмите на ссылку с подтверждением имейла.

  • Залогиньтесь с помощью имейла и пароля.

  • Выйдите.

Сброс тестового пароля

  • Залогиньтесь и выберите Forgot your password?
  • Выберите имейл, который вы использовали при регистрации аккаунта.
  • Вам будет отправлен имейл со ссылкой для сброса пароля. Проверьте имейл и нажмите на ссылку, чтобы сбросить пароль. После этого вы можете залогиниться, используя новый пароль.

Подтверждение имейла перед логином

С текущими шаблонами после регистрации пользователи автоматически логинятся. Далее мы изменим код, чтобы перед логином пользователи подтверждали имейл. Обновите действие [HttpPost] Login в файле AccountController.cs.

Примечание

Лучше всего не использовать производственные секреты при разработке и тестировании. Если вы публикуете приложение на Azure, то можете настроить секреты SendGrid как настройки приложения на Azure. Конфигурационная система считывает ключи из переменных среды.

Объединение аккаунтов

Вы можете объединить аккаунты, если кликните на ссылку для имейла. “RickAndMSFT@gmail.com” был создан как локальный логин, но вы можете сперва создать логин из социальной сети, а затем добавить локальный логин.

../../_images/rick.png

Нажмите на ссылку Manage. Обратите внимание, что с этим аккаунтом не связаны логины с социальных сетей.

../../_images/manage.png

Нажмите на ссылку к другому сервису и примите соглашение. Например, вот так:

../../_images/fb.png

Оба аккаунта объединены. Вы можете залогиниться с помощью любого из этих аккаунтов. Пользователи могут залогиниться с помощью локального аккаунта, если не смогут это сделать через социальную сеть.

Поделись хорошей новостью с друзьями!
Следи за новостями!