Potvrzení účtu a obnovení hesla v ASP.NET Core

Rick Anderson, Ponant a Joe Audette

V tomto kurzu se dozvíte, jak vytvořit aplikaci ASP.NET Core s potvrzením e-mailu a resetováním hesla. Tento kurz není počátečním tématem. Měli byste být obeznámeni:

Požadavky

Vytvoření a otestování webové aplikace s ověřováním

Spuštěním následujících příkazů vytvořte webovou aplikaci s ověřováním.

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

Registrace uživatele s potvrzením simulovaného e-mailu

Spusťte aplikaci, vyberte odkaz Zaregistrovat a zaregistrujte uživatele. Po registraci budete přesměrováni na /Identity/Account/RegisterConfirmation stránku, která obsahuje odkaz na simulaci potvrzení e-mailu:

  • Vyberte odkaz Click here to confirm your account.
  • Vyberte přihlašovací odkaz a přihlaste se pomocí stejných přihlašovacích údajů.
  • Hello YourEmail@provider.com! Vyberte odkaz, který přesměruje na /Identity/Account/Manage/PersonalData stránku.
  • Na levé straně vyberte kartu Osobní údaje a pak vyberte Odstranit.

Odkaz Click here to confirm your account se zobrazí, protože IEmailSender nebyl implementován a registrován v kontejneru injektáž závislostí. Podívejte se na RegisterConfirmation zdroj.

Poznámka:

Odkazy na dokumentaci k referenčnímu zdroji .NET obvykle načítají výchozí větev úložiště, která představuje aktuální vývoj pro příští verzi .NET. Pokud chcete vybrat značku pro konkrétní verzi, použijte rozevírací seznam pro přepnutí větví nebo značek. Další informace najdete v tématu Jak vybrat značku verze zdrojového kódu ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Konfigurace poskytovatele e-mailu

V tomto kurzu se SendGrid používá k odesílání e-mailů. K odeslání e-mailu je potřeba účet SendGrid a klíč. K odesílání e-mailů místo SMTP doporučujeme použít SendGrid nebo jinou e-mailovou službu. Zabezpečení a nastavení protokolu SMTP je obtížné.

Účet SendGrid může vyžadovat přidání odesílatele.

Vytvořte třídu pro načtení zabezpečeného e-mailového klíče. Pro tuto ukázku vytvořte Services/AuthMessageSenderOptions.cs:

namespace WebPWrecover.Services;

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

Konfigurace tajných kódů uživatelů SendGridu

SendGridKeyNastavte nástroj secret-manager. Příklad:

dotnet user-secrets set SendGridKey <key>

Successfully saved SendGridKey to the secret store.

Ve Windows ukládá Secret Manager páry klíčů a hodnot do secrets.json souboru v %APPDATA%/Microsoft/UserSecrets/<WebAppName-userSecretsId> adresáři.

Obsah secrets.json souboru není šifrovaný. Následující kód ukazuje secrets.json soubor. Hodnota SendGridKey byla odebrána.

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

Další informace najdete v vzoru Možnosti a konfigurace.

Instalace SendGridu

V tomto kurzu se dozvíte, jak přidat e-mailová oznámení prostřednictvím SendGridu, ale další poskytovatelé e-mailu je možné použít.

SendGrid Nainstalujte balíček NuGet:

V konzole Správce balíčků zadejte následující příkaz:

Install-Package SendGrid

Informace o registraci bezplatného účtu SendGrid najdete v tématu Začínáme s SendGridem zdarma.

Implementace IEmailSenderu

Pokud chcete implementovat IEmailSender, vytvořte Services/EmailSender.cs kód podobný následujícímu:

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}");
    }
}

Konfigurace aplikace pro podporu e-mailu

Do souboru Program.cs přidejte následující kód:

  • Přidat EmailSender jako přechodnou službu
  • AuthMessageSenderOptions Zaregistrujte instanci konfigurace.
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();

Zakázání výchozího ověření účtu při generování účtu Account.RegisterConfirmation

Tato část platí jenom v případě, že Account.RegisterConfirmation se vygeneruje. Tuto část přeskočte, pokud jste nevygenerovali Account.RegisterConfirmation.

Uživatel se přesměruje na Account.RegisterConfirmation místo, kde může vybrat odkaz, který má účet potvrzený. Výchozí hodnota Account.RegisterConfirmation se používá jenom pro testování, automatické ověření účtu by mělo být v produkční aplikaci zakázané.

Pokud chcete vyžadovat potvrzený účet a zabránit okamžitému přihlášení při registraci, nastavte DisplayConfirmAccountLink = false v souboru vygenerovaného /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs uživatelského rozhraní:

// 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();
        }
    }
}

Tento krok je nutný pouze v Account.RegisterConfirmation případě, že se vygeneruje. Neuskutečněná instance RegisterConfirmation automaticky zjistí, kdy je implementovaný a zaregistrovaný kontejner injektáže závislostí.

Registrace, potvrzení e-mailu a resetování hesla

Spusťte webovou aplikaci a otestujte tok potvrzení účtu a obnovení hesla.

  • Spuštění aplikace a registrace nového uživatele
  • Zkontrolujte svůj e-mail s odkazem na potvrzení účtu. Pokud e-mail nedostanete, podívejte se na ladicí e-mail .
  • Kliknutím na odkaz potvrďte svůj e-mail.
  • Přihlaste se pomocí svého e-mailu a hesla.
  • Odhlásit se.

Testování resetování hesla

  • Pokud jste přihlášení, vyberte Odhlásit se.
  • Vyberte odkaz Přihlásit se a vyberte odkaz Zapomněli jste heslo?
  • Zadejte e-mail, který jste použili k registraci účtu.
  • Odešle se e-mail s odkazem na resetování hesla. Zkontrolujte svůj e-mail a kliknutím na odkaz resetujte heslo. Po úspěšném resetování hesla se můžete přihlásit pomocí e-mailu a nového hesla.

Potvrzení opětovného odeslání e-mailu

Na přihlašovací stránce vyberte odkaz pro potvrzení opětovného odeslání e-mailu.

Změna časového limitu e-mailu a aktivity

Výchozí časový limit nečinnosti je 14 dnů. Následující kód nastaví časový limit nečinnosti na 5 dnů:

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

Změna životnosti všech tokenů ochrany dat

Následující kód změní časový limit všech tokenů ochrany dat na 3 hodiny:

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.

Integrované Identity tokeny uživatele (viz AspNetCore/src/Identity/Extensions.Core/src/TokenOptions.cs )mají časový limit jednoho dne.

Změna životnosti e-mailového tokenu

Výchozí životnost Identity tokenů uživatele je jeden den. Tato část ukazuje, jak změnit životnost e-mailového tokenu.

Přidejte vlastní a 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);
    }
}

Přidejte vlastního zprostředkovatele do kontejneru služby:

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.

Ladění e-mailu

Pokud vám nefunguje e-mail:

  • Nastavte zarážku EmailSender.Execute pro ověření SendGridClient.SendEmailAsync .
  • Vytvořte konzolovou aplikaci pro odesílání e-mailů pomocí podobného kódu EmailSender.Executejako .
  • Zkontrolujte stránku e-mailové aktivity.
  • Zkontrolujte složku spamu.
  • Zkuste jiný e-mailový alias u jiného poskytovatele e-mailu (Microsoft, Yahoo, Gmail atd.).
  • Zkuste odeslat do různých e-mailových účtů.

Osvědčeným postupem zabezpečení je nepoužívat produkční tajné kódy při testování a vývoji. Pokud publikujete aplikaci do Azure, nastavte tajné kódy SendGrid jako nastavení aplikace na portálu Azure Web App. Konfigurační systém je nastavený tak, aby načítal klíče z proměnných prostředí.

Kombinování sociálních a místních přihlašovacích účtů

Chcete-li dokončit tuto část, musíte nejprve povolit externího zprostředkovatele ověřování. Podívejte se na Ověřování pomocí Facebooku, Googlu a externího zprostředkovatele.

Místní a sociální účty můžete kombinovat kliknutím na svůj e-mailový odkaz. V následující sekvenci se "RickAndMSFT@gmail.com" nejprve vytvoří jako místní přihlášení. Nejprve ale můžete účet vytvořit jako přihlášení na sociální síti a pak přidat místní přihlášení.

Web application: RickAndMSFT@gmail.com user authenticated

Klikněte na odkaz Spravovat . Poznamenejte si 0 externích (sociálních přihlášení) přidružených k tomuto účtu.

Manage view

Klikněte na odkaz na jinou přihlašovací službu a přijměte žádosti o aplikaci. Na následujícím obrázku je Facebook externím zprostředkovatelem ověřování:

Manage your external logins view listing Facebook

Oba účty byly sloučeny. Můžete se přihlásit pomocí některého z účtů. Můžete chtít, aby uživatelé přidávali místní účty v případě, že je služba ověřování přihlášení k sociální síti, nebo pravděpodobně ztratili přístup ke svému účtu na sociálních sítích.

Povolení potvrzení účtu po tom, co má web uživatele

Povolení potvrzení účtu na webu s uživateli zamkne všechny stávající uživatele. Stávající uživatelé jsou uzamčení, protože jejich účty se nepotvrdí. Pokud chcete obejít stávající uzamčení uživatele, použijte jeden z následujících přístupů:

  • Aktualizujte databázi tak, aby označí všechny existující uživatele jako potvrzené.
  • Potvrďte existující uživatele. Například dávkové odesílání e-mailů s potvrzovanými odkazy.

Požadavky

.NET Core 3.0 SDK nebo novější

Vytvoření a otestování webové aplikace s ověřováním

Spuštěním následujících příkazů vytvořte webovou aplikaci s ověřováním.

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

Spusťte aplikaci, vyberte odkaz Zaregistrovat a zaregistrujte uživatele. Po registraci budete přesměrováni na /Identity/Account/RegisterConfirmation stránku, která obsahuje odkaz na simulaci potvrzení e-mailu:

  • Vyberte odkaz Click here to confirm your account.
  • Vyberte přihlašovací odkaz a přihlaste se pomocí stejných přihlašovacích údajů.
  • Hello YourEmail@provider.com! Vyberte odkaz, který vás přesměruje na /Identity/Account/Manage/PersonalData stránku.
  • Na levé straně vyberte kartu Osobní údaje a pak vyberte Odstranit.

Konfigurace poskytovatele e-mailu

V tomto kurzu se SendGrid používá k odesílání e-mailů. Můžete použít jiné poskytovatele e-mailu. K odesílání e-mailů doporučujeme použít SendGrid nebo jinou e-mailovou službu. Konfigurace protokolu SMTP je obtížná, takže pošta není označená jako spam.

Účet SendGrid může vyžadovat přidání odesílatele.

Vytvořte třídu pro načtení zabezpečeného e-mailového klíče. Pro tuto ukázku vytvořte Services/AuthMessageSenderOptions.cs:

namespace WebPWrecover.Services;

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

Konfigurace tajných kódů uživatelů SendGridu

SendGridKeyNastavte nástroj secret-manager. Příklad:

dotnet user-secrets set SendGridKey <SG.key>

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

Ve Windows ukládá Secret Manager páry klíčů a hodnot do secrets.json souboru v %APPDATA%/Microsoft/UserSecrets/<WebAppName-userSecretsId> adresáři.

Obsah secrets.json souboru není šifrovaný. Následující kód ukazuje secrets.json soubor. Hodnota SendGridKey byla odebrána.

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

Další informace najdete v vzoru Možnosti a konfigurace.

Instalace SendGridu

V tomto kurzu se dozvíte, jak přidat e-mailová oznámení přes SendGrid, ale e-maily můžete odesílat pomocí protokolu SMTP a dalších mechanismů.

SendGrid Nainstalujte balíček NuGet:

V konzole Správce balíčků zadejte následující příkaz:

Install-Package SendGrid

Informace o registraci bezplatného účtu SendGrid najdete v tématu Začínáme s SendGridem zdarma.

Implementace IEmailSenderu

Pokud chcete implementovat IEmailSender, vytvořte Services/EmailSender.cs kód podobný následujícímu:

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}");
    }
}

Konfigurace spuštění pro podporu e-mailu

Do metody v Startup.cs souboru přidejte následující kódConfigureServices:

  • Přidat EmailSender jako přechodnou službu
  • AuthMessageSenderOptions Zaregistrujte instanci konfigurace.
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();

Vygenerování registraceConfirmation

Postupujte podle pokynů pro generování a generování uživatelského rozhraníIdentityAccount\RegisterConfirmation.

Zakázání výchozího ověření účtu při generování účtu Account.RegisterConfirmation

Tato část platí jenom v případě, že Account.RegisterConfirmation se vygeneruje. Tuto část přeskočte, pokud jste nevygenerovali Account.RegisterConfirmation.

Uživatel se přesměruje na Account.RegisterConfirmation místo, kde může vybrat odkaz, který má účet potvrzený. Výchozí hodnota Account.RegisterConfirmation se používá jenom pro testování, automatické ověření účtu by mělo být v produkční aplikaci zakázané.

Pokud chcete vyžadovat potvrzený účet a zabránit okamžitému přihlášení při registraci, nastavte DisplayConfirmAccountLink = false v souboru vygenerovaného /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs uživatelského rozhraní:

// 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();
        }
    }
}

Tento krok je nutný pouze v Account.RegisterConfirmation případě, že se vygeneruje. Neuskutečněná instance RegisterConfirmation automaticky zjistí, kdy je implementovaný a zaregistrovaný kontejner injektáže závislostí.

Registrace, potvrzení e-mailu a resetování hesla

Spusťte webovou aplikaci a otestujte tok potvrzení účtu a obnovení hesla.

  • Spuštění aplikace a registrace nového uživatele
  • Zkontrolujte svůj e-mail s odkazem na potvrzení účtu. Pokud e-mail nedostanete, podívejte se na ladicí e-mail .
  • Kliknutím na odkaz potvrďte svůj e-mail.
  • Přihlaste se pomocí svého e-mailu a hesla.
  • Odhlásit se.

Testování resetování hesla

  • Pokud jste přihlášení, vyberte Odhlásit se.
  • Vyberte odkaz Přihlásit se a vyberte odkaz Zapomněli jste heslo?
  • Zadejte e-mail, který jste použili k registraci účtu.
  • Odešle se e-mail s odkazem na resetování hesla. Zkontrolujte svůj e-mail a kliknutím na odkaz resetujte heslo. Po úspěšném resetování hesla se můžete přihlásit pomocí e-mailu a nového hesla.

Potvrzení opětovného odeslání e-mailu

V ASP.NET Core 5.0 a novějším vyberte na přihlašovací stránce odkaz pro potvrzení opětovného odeslání e-mailu.

Změna časového limitu e-mailu a aktivity

Výchozí časový limit nečinnosti je 14 dnů. Následující kód nastaví časový limit nečinnosti na 5 dnů:

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

Změna životnosti všech tokenů ochrany dat

Následující kód změní časový limit všech tokenů ochrany dat na 3 hodiny:

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();
}

Integrované Identity tokeny uživatele (viz AspNetCore/src/Identity/Extensions.Core/src/TokenOptions.cs )mají časový limit jednoho dne.

Změna životnosti e-mailového tokenu

Výchozí životnost Identity tokenů uživatele je jeden den. Tato část ukazuje, jak změnit životnost e-mailového tokenu.

Přidejte vlastní a 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);
    }
}

Přidejte vlastního zprostředkovatele do kontejneru služby:

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();
}

Ladění e-mailu

Pokud vám nefunguje e-mail:

  • Nastavte zarážku EmailSender.Execute pro ověření SendGridClient.SendEmailAsync .
  • Vytvořte konzolovou aplikaci pro odesílání e-mailů pomocí podobného kódu EmailSender.Executejako .
  • Zkontrolujte stránku e-mailové aktivity.
  • Zkontrolujte složku spamu.
  • Zkuste jiný e-mailový alias u jiného poskytovatele e-mailu (Microsoft, Yahoo, Gmail atd.).
  • Zkuste odeslat do různých e-mailových účtů.

Osvědčeným postupem zabezpečení je nepoužívat produkční tajné kódy při testování a vývoji. Pokud publikujete aplikaci do Azure, nastavte tajné kódy SendGrid jako nastavení aplikace na portálu Azure Web App. Konfigurační systém je nastavený tak, aby načítal klíče z proměnných prostředí.

Kombinování sociálních a místních přihlašovacích účtů

Chcete-li dokončit tuto část, musíte nejprve povolit externího zprostředkovatele ověřování. Podívejte se na Ověřování pomocí Facebooku, Googlu a externího zprostředkovatele.

Místní a sociální účty můžete kombinovat kliknutím na svůj e-mailový odkaz. V následující sekvenci se "RickAndMSFT@gmail.com" nejprve vytvoří jako místní přihlášení. Nejprve ale můžete účet vytvořit jako přihlášení na sociální síti a pak přidat místní přihlášení.

Web application: RickAndMSFT@gmail.com user authenticated

Klikněte na odkaz Spravovat . Poznamenejte si 0 externích (sociálních přihlášení) přidružených k tomuto účtu.

Manage view

Klikněte na odkaz na jinou přihlašovací službu a přijměte žádosti o aplikaci. Na následujícím obrázku je Facebook externím zprostředkovatelem ověřování:

Manage your external logins view listing Facebook

Oba účty byly sloučeny. Můžete se přihlásit pomocí některého z účtů. Můžete chtít, aby uživatelé přidávali místní účty v případě, že je služba ověřování přihlášení k sociální síti, nebo pravděpodobně ztratili přístup ke svému účtu na sociálních sítích.

Povolení potvrzení účtu po tom, co má web uživatele

Povolení potvrzení účtu na webu s uživateli zamkne všechny stávající uživatele. Stávající uživatelé jsou uzamčení, protože jejich účty se nepotvrdí. Pokud chcete obejít stávající uzamčení uživatele, použijte jeden z následujících přístupů:

  • Aktualizujte databázi tak, aby označí všechny existující uživatele jako potvrzené.
  • Potvrďte existující uživatele. Například dávkové odesílání e-mailů s potvrzovanými odkazy.