Поделиться через


Подтверждение учетной записи и восстановление пароля в ASP.NET Core

Рик Андерсон, Понант и Джо Audette

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

Инструкции Blazor , добавляющие в инструкции или заменяющие инструкции в этой статье, см. в следующих ресурсах:

Необходимые компоненты

Создание и тестирование веб-приложения с проверкой подлинности

Выполните следующие команды, чтобы создать веб-приложение с проверкой подлинности.

dotnet new webapp -au Individual -o WebPWrecover
cd WebPWrecover
dotnet run

Регистрация пользователя с имитацией подтверждения электронной почты

Запустите приложение, выберите ссылку "Регистрация " и зарегистрируйте пользователя. После регистрации вы будете перенаправлены на /Identity/Account/RegisterConfirmation страницу, содержащую ссылку для имитации подтверждения электронной почты:

  • Выберите ссылку Click here to confirm your account.
  • Выберите ссылку для входа и войдите с теми же учетными данными.
  • Выберите ссылку Hello YourEmail@provider.com! , которая перенаправляется на страницу /Identity/Account/Manage/PersonalData .
  • Перейдите на вкладку "Персональные данные " слева и нажмите кнопку "Удалить".

Ссылка Click here to confirm your account отображается, так как IEmailSender не реализована и зарегистрирована в контейнере внедрения зависимостей. См. RegisterConfirmation источник.

Примечание.

По ссылкам в документации на справочные материалы по .NET обычно загружается ветвь репозитория по умолчанию, которая представляет текущую разработку для следующего выпуска .NET. Чтобы выбрать тег для определенного выпуска, используйте раскрывающийся список Switch branches or tags (Переключение ветвей или тегов). Дополнительные сведения см. в статье Выбор тега версии исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Настройка поставщика электронной почты

В этом руководстве SendGrid используется для отправки электронной почты. Для отправки электронной почты требуется учетная запись SendGrid и ключ. Мы рекомендуем использовать SendGrid или другую службу электронной почты для отправки электронной почты, а не SMTP. SMTP трудно защитить и настроить правильно.

Для учетной записи SendGrid может потребоваться добавить отправителя.

Создайте класс для получения безопасного ключа электронной почты. Для этого примера создайте Services/AuthMessageSenderOptions.cs:

namespace WebPWrecover.Services;

public class AuthMessageSenderOptions
{
    public string? SendGridKey { get; set; }
}

Настройка секретов пользователя SendGrid

SendGridKey Установите средство secret-manager. Например:

dotnet user-secrets set SendGridKey <key>

Successfully saved SendGridKey to the secret store.

В Windows диспетчер секретов хранит пары "ключи-значение" в файле в secrets.json каталоге %APPDATA%/Microsoft/UserSecrets/<WebAppName-userSecretsId> .

Содержимое secrets.json файла не шифруется. В следующей разметке secrets.json показан файл. Значение SendGridKey было удалено.

{
  "SendGridKey": "<key removed>"
}

Дополнительные сведения см. в шаблоне параметров и конфигурации.

Установка SendGrid

В этом руководстве показано, как добавить Уведомления по электронной почте через SendGrid, но другие поставщики электронной почты можно использовать.

SendGrid Установите пакет NuGet:

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

Install-Package SendGrid

См. статью "Начало работы с SendGrid для бесплатной регистрации для бесплатной учетной записи SendGrid".

Реализация IEmailSender

Чтобы реализовать IEmailSender, создайте Services/EmailSender.cs код, аналогичный следующему:

using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Options;
using SendGrid;
using SendGrid.Helpers.Mail;

namespace WebPWrecover.Services;

public class EmailSender : IEmailSender
{
    private readonly ILogger _logger;

    public EmailSender(IOptions<AuthMessageSenderOptions> optionsAccessor,
                       ILogger<EmailSender> logger)
    {
        Options = optionsAccessor.Value;
        _logger = logger;
    }

    public AuthMessageSenderOptions Options { get; } //Set with Secret Manager.

    public async Task SendEmailAsync(string toEmail, string subject, string message)
    {
        if (string.IsNullOrEmpty(Options.SendGridKey))
        {
            throw new Exception("Null SendGridKey");
        }
        await Execute(Options.SendGridKey, subject, message, toEmail);
    }

    public async Task Execute(string apiKey, string subject, string message, string toEmail)
    {
        var client = new SendGridClient(apiKey);
        var msg = new SendGridMessage()
        {
            From = new EmailAddress("Joe@contoso.com", "Password Recovery"),
            Subject = subject,
            PlainTextContent = message,
            HtmlContent = message
        };
        msg.AddTo(new EmailAddress(toEmail));

        // Disable click tracking.
        // See https://sendgrid.com/docs/User_Guide/Settings/tracking.html
        msg.SetClickTracking(false, false);
        var response = await client.SendEmailAsync(msg);
        _logger.LogInformation(response.IsSuccessStatusCode 
                               ? $"Email to {toEmail} queued successfully!"
                               : $"Failure Email to {toEmail}");
    }
}

Настройка приложения для поддержки электронной почты

Добавьте в файл Program.cs следующий код:

  • Добавьте EmailSender в качестве временной службы.
  • AuthMessageSenderOptions Зарегистрируйте экземпляр конфигурации.
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.EntityFrameworkCore;
using WebPWrecover.Data;
using WebPWrecover.Services;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();

builder.Services.AddTransient<IEmailSender, EmailSender>();
builder.Services.Configure<AuthMessageSenderOptions>(builder.Configuration);

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapRazorPages();

app.Run();

Отключение проверки учетной записи по умолчанию при создании шаблонов account.RegisterConfirmation

Этот раздел применяется только при Account.RegisterConfirmation создании шаблонов. Пропустите этот раздел, если вы не создали шаблон Account.RegisterConfirmation.

Пользователь перенаправляется на Account.RegisterConfirmation место, где можно выбрать ссылку, чтобы подтвердить учетную запись. Значение по умолчанию Account.RegisterConfirmation используется только для тестирования, автоматическая проверка учетной записи должна быть отключена в рабочем приложении.

Чтобы требовать подтвержденную учетную запись и предотвратить немедленный вход при регистрации, задайте DisplayConfirmAccountLink = false в шаблонном /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs файле:

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#nullable disable

using System;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.WebUtilities;

namespace WebPWrecover.Areas.Identity.Pages.Account
{
    [AllowAnonymous]
    public class RegisterConfirmationModel : PageModel
    {
        private readonly UserManager<IdentityUser> _userManager;
        private readonly IEmailSender _sender;

        public RegisterConfirmationModel(UserManager<IdentityUser> userManager, IEmailSender sender)
        {
            _userManager = userManager;
            _sender = sender;
        }

        /// <summary>
        ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public string Email { get; set; }

        /// <summary>
        ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public bool DisplayConfirmAccountLink { get; set; }

        /// <summary>
        ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public string EmailConfirmationUrl { get; set; }

        public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
        {
            if (email == null)
            {
                return RedirectToPage("/Index");
            }
            returnUrl = returnUrl ?? Url.Content("~/");

            var user = await _userManager.FindByEmailAsync(email);
            if (user == null)
            {
                return NotFound($"Unable to load user with email '{email}'.");
            }

            Email = email;
            // Once you add a real email sender, you should remove this code that lets you confirm the account
            DisplayConfirmAccountLink = false;
            if (DisplayConfirmAccountLink)
            {
                var userId = await _userManager.GetUserIdAsync(user);
                var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
                code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
                EmailConfirmationUrl = Url.Page(
                    "/Account/ConfirmEmail",
                    pageHandler: null,
                    values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
                    protocol: Request.Scheme);
            }

            return Page();
        }
    }
}

Этот шаг необходим только при Account.RegisterConfirmation создании шаблонов. Нестандартная регистрация RegisterConfirmation автоматически обнаруживает, когда IEmailSender была реализована и зарегистрирована в контейнере внедрения зависимостей.

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

Запустите веб-приложение и проверьте поток подтверждения учетной записи и восстановления паролей.

  • Запустите приложение и зарегистрируйте нового пользователя
  • Проверьте электронную почту по ссылке подтверждения учетной записи. Если вы не получите сообщение электронной почты, просмотрите отладочную почту .
  • Щелкните ссылку, чтобы подтвердить сообщение электронной почты.
  • Войдите с помощью электронной почты и пароля.
  • Выйти.

Тестирование сброса пароля

  • Если вы вошли в систему, выберите "Выйти".
  • Выберите ссылку "Войти" и щелкните ссылку "Забыл пароль"?
  • Введите сообщение электронной почты, которое вы использовали для регистрации учетной записи.
  • Отправляется сообщение электронной почты со ссылкой на сброс пароля. Проверьте электронную почту и щелкните ссылку, чтобы сбросить пароль. После успешного сброса пароля вы можете войти с помощью электронной почты и нового пароля.

Подтверждение повторной отправки электронной почты

Выберите ссылку подтверждения повторной отправки электронной почты на странице входа .

Изменение времени ожидания электронной почты и действий

Время ожидания бездействия по умолчанию — 14 дней. Следующий код задает время ожидания бездействия в течение 5 дней:

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.EntityFrameworkCore;
using WebPWrecover.Data;
using WebPWrecover.Services;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();

builder.Services.AddTransient<IEmailSender, EmailSender>();
builder.Services.Configure<AuthMessageSenderOptions>(builder.Configuration);

builder.Services.ConfigureApplicationCookie(o => {
    o.ExpireTimeSpan = TimeSpan.FromDays(5);
    o.SlidingExpiration = true;
});

var app = builder.Build();

// Code removed for brevity

Изменение срока жизни маркера защиты данных

Следующий код изменяет период ожидания всех маркеров защиты данных на 3 часа:

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.EntityFrameworkCore;
using WebPWrecover.Data;
using WebPWrecover.Services;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();

builder.Services.AddTransient<IEmailSender, EmailSender>();
builder.Services.Configure<AuthMessageSenderOptions>(builder.Configuration);

builder.Services.Configure<DataProtectionTokenProviderOptions>(o =>
       o.TokenLifespan = TimeSpan.FromHours(3));

var app = builder.Build();

// Code removed for brevity.

Встроенные Identity маркеры пользователей (см . раздел AspNetCore/src/IdentityExtensions.Core/src/TokenOptions.cs )имеют однодневное время ожидания.

Изменение срока жизни маркера электронной почты

Срок действия маркера по умолчанию для маркеров Identity пользователя составляет один день. В этом разделе показано, как изменить срок жизни маркера электронной почты.

Добавление пользовательского DataProtectorTokenProvider<TUser> и DataProtectionTokenProviderOptions:

public class CustomEmailConfirmationTokenProvider<TUser>
                              :  DataProtectorTokenProvider<TUser> where TUser : class
{
    public CustomEmailConfirmationTokenProvider(
        IDataProtectionProvider dataProtectionProvider,
        IOptions<EmailConfirmationTokenProviderOptions> options,
        ILogger<DataProtectorTokenProvider<TUser>> logger)
                                       : base(dataProtectionProvider, options, logger)
    {

    }
}
public class EmailConfirmationTokenProviderOptions : DataProtectionTokenProviderOptions
{
    public EmailConfirmationTokenProviderOptions()
    {
        Name = "EmailDataProtectorTokenProvider";
        TokenLifespan = TimeSpan.FromHours(4);
    }
}

Добавьте настраиваемого поставщика в контейнер службы:

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.EntityFrameworkCore;
using WebPWrecover.Data;
using WebPWrecover.Services;
using WebPWrecover.TokenProviders;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(config =>
{
    config.SignIn.RequireConfirmedEmail = true;
    config.Tokens.ProviderMap.Add("CustomEmailConfirmation",
        new TokenProviderDescriptor(
            typeof(CustomEmailConfirmationTokenProvider<IdentityUser>)));
    config.Tokens.EmailConfirmationTokenProvider = "CustomEmailConfirmation";
}).AddEntityFrameworkStores<ApplicationDbContext>();

builder.Services.AddTransient<CustomEmailConfirmationTokenProvider<IdentityUser>>();

builder.Services.AddRazorPages();

builder.Services.AddTransient<IEmailSender, EmailSender>();
builder.Services.Configure<AuthMessageSenderOptions>(builder.Configuration);

var app = builder.Build();

// Code removed for brevity.

Отладка электронной почты

Если вы не можете получить электронную почту, выполните следующие действия:

  • Задайте точку останова для EmailSender.Execute проверки SendGridClient.SendEmailAsync .
  • Создайте консольное приложение для отправки электронной почты с помощью аналогичного кода EmailSender.Execute.
  • Просмотрите страницу действия электронной почты.
  • Проверьте папку нежелательной почты.
  • Попробуйте другой псевдоним электронной почты в другом поставщике электронной почты (Microsoft, Yahoo, Gmail и т. д.)
  • Попробуйте отправить в разные учетные записи электронной почты.

Рекомендуется не использовать рабочие секреты в тестировании и разработке. При публикации приложения в Azure задайте секреты SendGrid в качестве параметров приложения на портале веб-приложения Azure. Система конфигурации настроена для чтения ключей из переменных среды.

Объединение учетных записей для входа в социальных сетях и локальных учетных записей входа

Чтобы завершить этот раздел, необходимо сначала включить внешний поставщик проверки подлинности. Ознакомьтесь с проверкой подлинности Facebook, Google и внешним поставщиком.

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

Веб-приложение: RickAndMSFT@gmail.com проверка подлинности пользователя

Щелкните ссылку "Управление ". Обратите внимание на внешние (социальные имена входа), связанные с этой учетной записью.

Управление представлением

Щелкните ссылку на другую службу входа и примите запросы приложения. На следующем изображении Facebook является внешним поставщиком проверки подлинности:

Управление внешними именами входа в списке Facebook

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

Включение подтверждения учетной записи после того, как сайт имеет пользователей

Включение подтверждения учетной записи на сайте с пользователями блокирует всех существующих пользователей. Существующие пользователи заблокированы, так как их учетные записи не подтверждены. Чтобы обойти существующую блокировку пользователей, используйте один из следующих подходов:

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

Необходимые компоненты

Пакет SDK для .NET Core 3.0 или более поздней версии

Создание и тестирование веб-приложения с проверкой подлинности

Выполните следующие команды, чтобы создать веб-приложение с проверкой подлинности.

dotnet new webapp -au Individual -uld -o WebPWrecover
cd WebPWrecover
dotnet run

Запустите приложение, выберите ссылку "Регистрация " и зарегистрируйте пользователя. После регистрации вы будете перенаправлены на /Identity/Account/RegisterConfirmation страницу, содержащую ссылку для имитации подтверждения электронной почты:

  • Выберите ссылку Click here to confirm your account.
  • Выберите ссылку для входа и войдите с теми же учетными данными.
  • Выберите ссылку Hello YourEmail@provider.com! , которая перенаправляет вас на страницу /Identity/Account/Manage/PersonalData .
  • Перейдите на вкладку "Персональные данные " слева и нажмите кнопку "Удалить".

Настройка поставщика электронной почты

В этом руководстве SendGrid используется для отправки электронной почты. Вы можете использовать другие поставщики электронной почты. Мы рекомендуем использовать SendGrid или другую службу электронной почты для отправки электронной почты. SMTP сложно настроить так, чтобы почта не помечена как спам.

Для учетной записи SendGrid может потребоваться добавить отправителя.

Создайте класс для получения безопасного ключа электронной почты. Для этого примера создайте Services/AuthMessageSenderOptions.cs:

namespace WebPWrecover.Services;

public class AuthMessageSenderOptions
{
    public string? SendGridKey { get; set; }
}

Настройка секретов пользователя SendGrid

SendGridKey Установите средство secret-manager. Например:

dotnet user-secrets set SendGridKey <SG.key>

Successfully saved SendGridKey = SG.keyVal to the secret store.

В Windows диспетчер секретов хранит пары "ключи-значение" в файле в secrets.json каталоге %APPDATA%/Microsoft/UserSecrets/<WebAppName-userSecretsId> .

Содержимое secrets.json файла не шифруется. В следующей разметке secrets.json показан файл. Значение SendGridKey было удалено.

{
  "SendGridKey": "<key removed>"
}

Дополнительные сведения см. в шаблоне параметров и конфигурации.

Установка SendGrid

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

SendGrid Установите пакет NuGet:

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

Install-Package SendGrid

См. статью "Начало работы с SendGrid для бесплатной регистрации для бесплатной учетной записи SendGrid".

Реализация IEmailSender

Чтобы реализовать IEmailSender, создайте Services/EmailSender.cs код, аналогичный следующему:

using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Options;
using SendGrid;
using SendGrid.Helpers.Mail;

namespace WebPWrecover.Services;

public class EmailSender : IEmailSender
{
    private readonly ILogger _logger;

    public EmailSender(IOptions<AuthMessageSenderOptions> optionsAccessor,
                       ILogger<EmailSender> logger)
    {
        Options = optionsAccessor.Value;
        _logger = logger;
    }

    public AuthMessageSenderOptions Options { get; } //Set with Secret Manager.

    public async Task SendEmailAsync(string toEmail, string subject, string message)
    {
        if (string.IsNullOrEmpty(Options.SendGridKey))
        {
            throw new Exception("Null SendGridKey");
        }
        await Execute(Options.SendGridKey, subject, message, toEmail);
    }

    public async Task Execute(string apiKey, string subject, string message, string toEmail)
    {
        var client = new SendGridClient(apiKey);
        var msg = new SendGridMessage()
        {
            From = new EmailAddress("Joe@contoso.com", "Password Recovery"),
            Subject = subject,
            PlainTextContent = message,
            HtmlContent = message
        };
        msg.AddTo(new EmailAddress(toEmail));

        // Disable click tracking.
        // See https://sendgrid.com/docs/User_Guide/Settings/tracking.html
        msg.SetClickTracking(false, false);
        var response = await client.SendEmailAsync(msg);
        _logger.LogInformation(response.IsSuccessStatusCode 
                               ? $"Email to {toEmail} queued successfully!"
                               : $"Failure Email to {toEmail}");
    }
}

Настройка запуска для поддержки электронной почты

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

  • Добавьте EmailSender в качестве временной службы.
  • AuthMessageSenderOptions Зарегистрируйте экземпляр конфигурации.
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.EntityFrameworkCore;
using WebPWrecover.Data;
using WebPWrecover.Services;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();

builder.Services.AddTransient<IEmailSender, EmailSender>();
builder.Services.Configure<AuthMessageSenderOptions>(builder.Configuration);

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapRazorPages();

app.Run();

Шаблон RegisterConfirmation

Следуйте инструкциям по шаблону Identity и шаблону Account\RegisterConfirmation.

Отключение проверки учетной записи по умолчанию при создании шаблонов account.RegisterConfirmation

Этот раздел применяется только при Account.RegisterConfirmation создании шаблонов. Пропустите этот раздел, если вы не создали шаблон Account.RegisterConfirmation.

Пользователь перенаправляется на Account.RegisterConfirmation место, где можно выбрать ссылку, чтобы подтвердить учетную запись. Значение по умолчанию Account.RegisterConfirmation используется только для тестирования, автоматическая проверка учетной записи должна быть отключена в рабочем приложении.

Чтобы требовать подтвержденную учетную запись и предотвратить немедленный вход при регистрации, задайте DisplayConfirmAccountLink = false в шаблонном /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs файле:

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#nullable disable

using System;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.WebUtilities;

namespace WebPWrecover.Areas.Identity.Pages.Account
{
    [AllowAnonymous]
    public class RegisterConfirmationModel : PageModel
    {
        private readonly UserManager<IdentityUser> _userManager;
        private readonly IEmailSender _sender;

        public RegisterConfirmationModel(UserManager<IdentityUser> userManager, IEmailSender sender)
        {
            _userManager = userManager;
            _sender = sender;
        }

        /// <summary>
        ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public string Email { get; set; }

        /// <summary>
        ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public bool DisplayConfirmAccountLink { get; set; }

        /// <summary>
        ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public string EmailConfirmationUrl { get; set; }

        public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
        {
            if (email == null)
            {
                return RedirectToPage("/Index");
            }
            returnUrl = returnUrl ?? Url.Content("~/");

            var user = await _userManager.FindByEmailAsync(email);
            if (user == null)
            {
                return NotFound($"Unable to load user with email '{email}'.");
            }

            Email = email;
            // Once you add a real email sender, you should remove this code that lets you confirm the account
            DisplayConfirmAccountLink = false;
            if (DisplayConfirmAccountLink)
            {
                var userId = await _userManager.GetUserIdAsync(user);
                var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
                code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
                EmailConfirmationUrl = Url.Page(
                    "/Account/ConfirmEmail",
                    pageHandler: null,
                    values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
                    protocol: Request.Scheme);
            }

            return Page();
        }
    }
}

Этот шаг необходим только при Account.RegisterConfirmation создании шаблонов. Нестандартная регистрация RegisterConfirmation автоматически обнаруживает, когда IEmailSender была реализована и зарегистрирована в контейнере внедрения зависимостей.

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

Запустите веб-приложение и проверьте поток подтверждения учетной записи и восстановления паролей.

  • Запустите приложение и зарегистрируйте нового пользователя
  • Проверьте электронную почту по ссылке подтверждения учетной записи. Если вы не получите сообщение электронной почты, просмотрите отладочную почту .
  • Щелкните ссылку, чтобы подтвердить сообщение электронной почты.
  • Войдите с помощью электронной почты и пароля.
  • Выйти.

Тестирование сброса пароля

  • Если вы вошли в систему, выберите "Выйти".
  • Выберите ссылку "Войти" и щелкните ссылку "Забыл пароль"?
  • Введите сообщение электронной почты, которое вы использовали для регистрации учетной записи.
  • Отправляется сообщение электронной почты со ссылкой на сброс пароля. Проверьте электронную почту и щелкните ссылку, чтобы сбросить пароль. После успешного сброса пароля вы можете войти с помощью электронной почты и нового пароля.

Подтверждение повторной отправки электронной почты

В ASP.NET Core 5.0 и более поздних версий выберите ссылку подтверждения повторной отправки электронной почты на странице входа .

Изменение времени ожидания электронной почты и действий

Время ожидания бездействия по умолчанию — 14 дней. Следующий код задает время ожидания бездействия в течение 5 дней:

services.ConfigureApplicationCookie(o => {
    o.ExpireTimeSpan = TimeSpan.FromDays(5);
    o.SlidingExpiration = true;
});

Изменение срока жизни маркера защиты данных

Следующий код изменяет период ожидания всех маркеров защиты данных на 3 часа:

public void ConfigureServices(IServiceCollection services)
{

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>(
                  options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.Configure<DataProtectionTokenProviderOptions>(o =>
       o.TokenLifespan = TimeSpan.FromHours(3));

    services.AddTransient<IEmailSender, EmailSender>();
    services.Configure<AuthMessageSenderOptions>(Configuration);

    services.AddRazorPages();
}

Встроенные Identity маркеры пользователей (см . раздел AspNetCore/src/IdentityExtensions.Core/src/TokenOptions.cs )имеют однодневное время ожидания.

Изменение срока жизни маркера электронной почты

Срок действия маркера по умолчанию для маркеров Identity пользователя составляет один день. В этом разделе показано, как изменить срок жизни маркера электронной почты.

Добавление пользовательского DataProtectorTokenProvider<TUser> и DataProtectionTokenProviderOptions:

public class CustomEmailConfirmationTokenProvider<TUser>
                                       : DataProtectorTokenProvider<TUser> where TUser : class
{
    public CustomEmailConfirmationTokenProvider(IDataProtectionProvider dataProtectionProvider,
        IOptions<EmailConfirmationTokenProviderOptions> options,
        ILogger<DataProtectorTokenProvider<TUser>> logger)
                                          : base(dataProtectionProvider, options, logger)
    {

    }
}
public class EmailConfirmationTokenProviderOptions : DataProtectionTokenProviderOptions
{
    public EmailConfirmationTokenProviderOptions()
    {
        Name = "EmailDataProtectorTokenProvider";
        TokenLifespan = TimeSpan.FromHours(4);
    }
}

Добавьте настраиваемого поставщика в контейнер службы:

public void ConfigureServices(IServiceCollection services)
{

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>(config =>
    {
        config.SignIn.RequireConfirmedEmail = true;
        config.Tokens.ProviderMap.Add("CustomEmailConfirmation",
            new TokenProviderDescriptor(
                typeof(CustomEmailConfirmationTokenProvider<IdentityUser>)));
        config.Tokens.EmailConfirmationTokenProvider = "CustomEmailConfirmation";
      }).AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddTransient<CustomEmailConfirmationTokenProvider<IdentityUser>>();

    services.AddTransient<IEmailSender, EmailSender>();
    services.Configure<AuthMessageSenderOptions>(Configuration);

    services.AddRazorPages();
}

Отладка электронной почты

Если вы не можете получить электронную почту, выполните следующие действия:

  • Задайте точку останова для EmailSender.Execute проверки SendGridClient.SendEmailAsync .
  • Создайте консольное приложение для отправки электронной почты с помощью аналогичного кода EmailSender.Execute.
  • Просмотрите страницу действия электронной почты.
  • Проверьте папку нежелательной почты.
  • Попробуйте другой псевдоним электронной почты в другом поставщике электронной почты (Microsoft, Yahoo, Gmail и т. д.)
  • Попробуйте отправить в разные учетные записи электронной почты.

Рекомендуется не использовать рабочие секреты в тестировании и разработке. При публикации приложения в Azure задайте секреты SendGrid в качестве параметров приложения на портале веб-приложения Azure. Система конфигурации настроена для чтения ключей из переменных среды.

Объединение учетных записей для входа в социальных сетях и локальных учетных записей входа

Чтобы завершить этот раздел, необходимо сначала включить внешний поставщик проверки подлинности. Ознакомьтесь с проверкой подлинности Facebook, Google и внешним поставщиком.

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

Веб-приложение: RickAndMSFT@gmail.com проверка подлинности пользователя

Щелкните ссылку "Управление ". Обратите внимание на внешние (социальные имена входа), связанные с этой учетной записью.

Управление представлением

Щелкните ссылку на другую службу входа и примите запросы приложения. На следующем изображении Facebook является внешним поставщиком проверки подлинности:

Управление внешними именами входа в списке Facebook

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

Включение подтверждения учетной записи после того, как сайт имеет пользователей

Включение подтверждения учетной записи на сайте с пользователями блокирует всех существующих пользователей. Существующие пользователи заблокированы, так как их учетные записи не подтверждены. Чтобы обойти существующую блокировку пользователей, используйте один из следующих подходов:

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