Dela via


Kontobekräftelse och lösenordsåterställning i ASP.NET Core

Av Rick Anderson, Ponant och Joe Audette

Den här självstudien visar hur du skapar en ASP.NET Core-app med e-postbekräftelse och lösenordsåterställning. Den här självstudien är inte ett nybörjarämne. Du bör känna till:

Vägledning Blazor , som lägger till eller ersätter vägledningen i den här artikeln, finns i följande resurser:

Förutsättningar

Skapa och testa en webbapp med autentisering

Kör följande kommandon för att skapa en webbapp med autentisering.

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

Registrera användare med simulerad e-postbekräftelse

Kör appen, välj länken Registrera och registrera en användare. När du har registrerat dig omdirigeras du till sidan /Identity/Account/RegisterConfirmation som innehåller en länk för att simulera e-postbekräftelse:

  • Välj länken Click here to confirm your account .
  • Välj länken Inloggning och logga in med samma autentiseringsuppgifter.
  • Välj länken Hello YourEmail@provider.com! som omdirigeras till sidan /Identity/Account/Manage/PersonalData .
  • Välj fliken Personliga data till vänster och välj sedan Ta bort.

Länken Click here to confirm your account visas eftersom en IEmailSender inte har implementerats och registrerats i beroendeinjektionscontainern. Se källanRegisterConfirmation.

Anmärkning

Dokumentationslänkar till .NET-referenskällan läser vanligtvis in lagringsplatsens standardgren, vilket representerar den aktuella utvecklingen för nästa version av .NET. Om du vill välja en tagg för en specifik version använder du listrutan Välj bland grenar eller taggar. Mer information finns i Så här väljer du en versionstagg för ASP.NET Core-källkod (dotnet/AspNetCore.Docs #26205).

Konfigurera en e-postleverantör

I den här självstudien används SendGrid för att skicka e-post. Ett SendGrid-konto och en nyckel krävs för att skicka e-post. Vi rekommenderar att du använder SendGrid eller en annan e-posttjänst för att skicka e-post i stället för SMTP. SMTP är svårt att skydda och konfigurera korrekt.

SendGrid-kontot kan kräva att en avsändare läggs till.

Skapa en klass för att hämta den säkra e-postnyckeln. För det här exemplet skapar du Services/AuthMessageSenderOptions.cs:

namespace WebPWrecover.Services;

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

Konfigurera SendGrid-användarhemligheter

Ställ in SendGridKey med verktyget secret-manager. Till exempel:

dotnet user-secrets set SendGridKey <key>

Successfully saved SendGridKey to the secret store.

I Windows lagrar Secret Manager nycklar/värdepar i en secrets.json fil i %APPDATA%/Microsoft/UserSecrets/<WebAppName-userSecretsId> katalogen.

Innehållet i secrets.json filen är inte krypterat. Följande markering visar secrets.json filen. Värdet SendGridKey har tagits bort.

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

För mer information, se Alternativmönstret och konfigurationen.

Installera SendGrid

Den här självstudien visar hur du lägger till e-postaviseringar via SendGrid, men andra e-postleverantörer kan användas.

Installera NuGet-paketet SendGrid :

Från Package Manager-konsolen anger du följande kommando:

Install-Package SendGrid

Se Kom igång med SendGrid kostnadsfritt för att registrera dig för ett kostnadsfritt SendGrid-konto.

Implementera IEmailSender

Om du vill implementera IEmailSenderskapar du Services/EmailSender.cs med kod som liknar följande:

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

Konfigurera appen för att stödja e-post

Lägg till följande kod i Program.cs-filen:

  • Lägg till EmailSender som en tillfällig tjänst.
  • Registrera konfigurationsinstansen 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();

Inaktivera standardverifiering av konto när Account.RegisterConfirmation har kodats

Det här avsnittet gäller endast när Account.RegisterConfirmation är scaffolded. Hoppa över det här avsnittet om du inte har scaffolded Account.RegisterConfirmation.

Användaren omdirigeras till den Account.RegisterConfirmation där de kan välja en länk för att få kontot bekräftat. Standardvärdet Account.RegisterConfirmation används endast för testning. Automatisk kontoverifiering ska inaktiveras i en produktionsapp.

Om du vill kräva ett bekräftat konto och förhindra omedelbar inloggning vid registreringen anger du DisplayConfirmAccountLink = false i den scaffolded /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs filen:

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

Det här steget är bara nödvändigt när Account.RegisterConfirmation är autogenererat. Den utan stödstruktur RegisterConfirmation identifierar automatiskt när en IEmailSender har implementerats och registrerats med beroendeinjektionscontainern.

Registrera, bekräfta e-post och återställa lösenord

Kör webbappen och testa flödet för kontobekräftelse och lösenordsåterställning.

  • Kör appen och registrera en ny användare
  • Kontrollera din e-post för länken för kontobekräftelse. Se Felsöka e-post om du inte får e-postmeddelandet.
  • Klicka på länken för att bekräfta din e-post.
  • Logga in med din e-post och ditt lösenord.
  • Logga ut.

Testa återställning av lösenord

  • Om du är inloggad väljer du Logga ut.
  • Välj länken Logga in och välj länken Har du glömt lösenordet?
  • Ange e-postmeddelandet som du använde för att registrera kontot.
  • Ett e-postmeddelande med en länk för att återställa lösenordet skickas. Kontrollera din e-post och klicka på länken för att återställa lösenordet. När lösenordet har återställts kan du logga in med din e-post och ditt nya lösenord.

Skicka e-postbekräftelse igen

Välj länken Skicka e-postbekräftelse igen på inloggningssidan .

Ändra tidsgränsen för e-post och aktivitet

Standardtidsgränsen för inaktivitet är 14 dagar. Följande kod anger tidsgränsen för inaktivitet till 5 dagar:

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

Ändra alla livslängder för dataskyddstoken

Följande kod ändrar tidsgränsen för alla dataskyddstoken till 3 timmar:

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.

De inbyggda Identity användartoken (se AspNetCore/src/Identity/Extensions.Core/src/TokenOptions.cs )har en timeout på en dag.

Ändra livslängden för e-posttoken

Standardtokens livslängd för Identity användartoken är en dag. Det här avsnittet visar hur du ändrar livslängden för e-posttoken.

Lägg till en anpassad DataProtectorTokenProvider<TUser> och 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);
    }
}

Lägg till den anpassade providern i tjänstcontainern:

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.

Felsökning av e-post

Om du inte kan få e-post att fungera:

  • Ange en brytpunkt i EmailSender.Execute för att verifiera att SendGridClient.SendEmailAsync anropas.
  • Skapa en konsolapp för att skicka e-post med liknande kod som EmailSender.Execute.
  • Granska sidan E-postaktivitet .
  • Kontrollera skräppostmappen.
  • Prova ett annat e-postalias på en annan e-postleverantör (Microsoft, Yahoo, Gmail osv.)
  • Prova att skicka till olika e-postkonton.

Ett säkerhetstips är att inte använda produktionshemligheter i test och utveckling. Om du publicerar appen till Azure anger du SendGrid-hemligheterna som programinställningar i Azure Web App-portalen. Konfigurationssystemet är konfigurerat för att läsa nycklar från miljövariabler.

Kombinera sociala och lokala inloggningskonton

För att slutföra det här avsnittet måste du först aktivera en extern autentiseringsprovider. Se Facebook, Google och extern providerautentisering.

Du kan kombinera lokala och sociala konton genom att klicka på din e-postlänk. I följande sekvens skapas "RickAndMSFT@gmail.com" först som en lokal inloggning. Du kan dock skapa kontot som en social inloggning först och sedan lägga till en lokal inloggning.

Webbprogram: RickAndMSFT@gmail.com användaren autentiserad

Klicka på länken Hantera . Observera de 0 externa (sociala inloggningar) som är associerade med det här kontot.

Hantera vy

Klicka på länken till en annan inloggningstjänst och godkänn appbegäranden. I följande bild är Facebook den externa autentiseringsprovidern:

Hantera din externa inloggningsvy som visar Facebook

De två kontona har kombinerats. Du kan logga in med något av kontona. Du kanske vill att dina användare ska lägga till lokala konton om deras autentiseringstjänst för social inloggning är nere, eller mer troligt att de har förlorat åtkomsten till sitt sociala konto.

Aktivera kontobekräftelse när en webbplats har användare

Aktivering av kontobekräftelse på en webbplats med användare låser alla befintliga användare. Befintliga användare är utelåst eftersom deras konton inte är bekräftade. Använd någon av följande metoder för att kringgå befintlig användarutelåsning:

  • Uppdatera databasen för att markera alla befintliga användare som bekräftade.
  • Bekräfta befintliga användare. Till exempel batch-skicka e-postmeddelanden med bekräftelselänkar.

Förutsättningar

.NET Core 3.0 eller senare SDK

Skapa och testa en webbapp med autentisering

Kör följande kommandon för att skapa en webbapp med autentisering.

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

Kör appen, välj länken Registrera och registrera en användare. När du har registrerat dig omdirigeras du till sidan /Identity/Account/RegisterConfirmation som innehåller en länk för att simulera e-postbekräftelse:

  • Välj länken Click here to confirm your account .
  • Välj länken Inloggning och logga in med samma autentiseringsuppgifter.
  • Välj länken Hello YourEmail@provider.com! som omdirigerar dig till sidan /Identity/Account/Manage/PersonalData .
  • Välj fliken Personliga data till vänster och välj sedan Ta bort.

Konfigurera en e-postleverantör

I den här självstudien används SendGrid för att skicka e-post. Du kan använda andra e-postleverantörer. Vi rekommenderar att du använder SendGrid eller en annan e-posttjänst för att skicka e-post. SMTP är svårt att konfigurera så e-post markeras inte som skräppost.

SendGrid-kontot kan kräva att en avsändare läggs till.

Skapa en klass för att hämta den säkra e-postnyckeln. För det här exemplet skapar du Services/AuthMessageSenderOptions.cs:

namespace WebPWrecover.Services;

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

Konfigurera SendGrid-användarhemligheter

Ställ in SendGridKey med verktyget secret-manager. Till exempel:

dotnet user-secrets set SendGridKey <SG.key>

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

I Windows lagrar Secret Manager nycklar/värdepar i en secrets.json fil i %APPDATA%/Microsoft/UserSecrets/<WebAppName-userSecretsId> katalogen.

Innehållet i secrets.json filen är inte krypterat. Följande markering visar secrets.json filen. Värdet SendGridKey har tagits bort.

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

För mer information, se Alternativmönstret och konfigurationen.

Installera SendGrid

Den här självstudien visar hur du lägger till e-postaviseringar via SendGrid, men du kan skicka e-post med SMTP och andra mekanismer.

Installera NuGet-paketet SendGrid :

Från Package Manager-konsolen anger du följande kommando:

Install-Package SendGrid

Se Kom igång med SendGrid kostnadsfritt för att registrera dig för ett kostnadsfritt SendGrid-konto.

Implementera IEmailSender

Om du vill implementera IEmailSenderskapar du Services/EmailSender.cs med kod som liknar följande:

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

Konfigurera start för att stödja e-post

Lägg till följande kod i ConfigureServices -metoden i Startup.cs filen:

  • Lägg till EmailSender som en tillfällig tjänst.
  • Registrera konfigurationsinstansen 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();

Mall för Registreringsbekräftelse

Följ anvisningarna för scaffold Identity och scaffold Account\RegisterConfirmation.

Inaktivera standardverifiering av konto när Account.RegisterConfirmation har kodats

Det här avsnittet gäller endast när Account.RegisterConfirmation är scaffolded. Hoppa över det här avsnittet om du inte har scaffolded Account.RegisterConfirmation.

Användaren omdirigeras till den Account.RegisterConfirmation där de kan välja en länk för att få kontot bekräftat. Standardvärdet Account.RegisterConfirmation används endast för testning. Automatisk kontoverifiering ska inaktiveras i en produktionsapp.

Om du vill kräva ett bekräftat konto och förhindra omedelbar inloggning vid registreringen anger du DisplayConfirmAccountLink = false i den scaffolded /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs filen:

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

Det här steget är bara nödvändigt när Account.RegisterConfirmation är autogenererat. Den utan stödstruktur RegisterConfirmation identifierar automatiskt när en IEmailSender har implementerats och registrerats med beroendeinjektionscontainern.

Registrera, bekräfta e-post och återställa lösenord

Kör webbappen och testa flödet för kontobekräftelse och lösenordsåterställning.

  • Kör appen och registrera en ny användare
  • Kontrollera din e-post för länken för kontobekräftelse. Se Felsöka e-post om du inte får e-postmeddelandet.
  • Klicka på länken för att bekräfta din e-post.
  • Logga in med din e-post och ditt lösenord.
  • Logga ut.

Testa återställning av lösenord

  • Om du är inloggad väljer du Logga ut.
  • Välj länken Logga in och välj länken Har du glömt lösenordet?
  • Ange e-postmeddelandet som du använde för att registrera kontot.
  • Ett e-postmeddelande med en länk för att återställa lösenordet skickas. Kontrollera din e-post och klicka på länken för att återställa lösenordet. När lösenordet har återställts kan du logga in med din e-post och ditt nya lösenord.

Skicka e-postbekräftelse igen

I .NET 5 eller senare väljer du länken Skicka e-postbekräftelse igeninloggningssidan .

Ändra tidsgränsen för e-post och aktivitet

Standardtidsgränsen för inaktivitet är 14 dagar. Följande kod anger tidsgränsen för inaktivitet till 5 dagar:

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

Ändra alla livslängder för dataskyddstoken

Följande kod ändrar tidsgränsen för alla dataskyddstoken till 3 timmar:

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

De inbyggda Identity användartoken (se AspNetCore/src/Identity/Extensions.Core/src/TokenOptions.cs )har en timeout på en dag.

Ändra livslängden för e-posttoken

Standardtokens livslängd för Identity användartoken är en dag. Det här avsnittet visar hur du ändrar livslängden för e-posttoken.

Lägg till en anpassad DataProtectorTokenProvider<TUser> och 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);
    }
}

Lägg till den anpassade providern i tjänstcontainern:

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

Felsökning av e-post

Om du inte kan få e-post att fungera:

  • Ange en brytpunkt i EmailSender.Execute för att verifiera att SendGridClient.SendEmailAsync anropas.
  • Skapa en konsolapp för att skicka e-post med liknande kod som EmailSender.Execute.
  • Granska sidan E-postaktivitet .
  • Kontrollera skräppostmappen.
  • Prova ett annat e-postalias på en annan e-postleverantör (Microsoft, Yahoo, Gmail osv.)
  • Prova att skicka till olika e-postkonton.

Ett säkerhetstips är att inte använda produktionshemligheter i test och utveckling. Om du publicerar appen till Azure anger du SendGrid-hemligheterna som programinställningar i Azure Web App-portalen. Konfigurationssystemet är konfigurerat för att läsa nycklar från miljövariabler.

Kombinera sociala och lokala inloggningskonton

För att slutföra det här avsnittet måste du först aktivera en extern autentiseringsprovider. Se Facebook, Google och extern providerautentisering.

Du kan kombinera lokala och sociala konton genom att klicka på din e-postlänk. I följande sekvens skapas "RickAndMSFT@gmail.com" först som en lokal inloggning. Du kan dock skapa kontot som en social inloggning först och sedan lägga till en lokal inloggning.

Webbprogram: RickAndMSFT@gmail.com användaren autentiserad

Klicka på länken Hantera . Observera de 0 externa (sociala inloggningar) som är associerade med det här kontot.

Hantera vy

Klicka på länken till en annan inloggningstjänst och godkänn appbegäranden. I följande bild är Facebook den externa autentiseringsprovidern:

Hantera din externa inloggningsvy som visar Facebook

De två kontona har kombinerats. Du kan logga in med något av kontona. Du kanske vill att dina användare ska lägga till lokala konton om deras autentiseringstjänst för social inloggning är nere, eller mer troligt att de har förlorat åtkomsten till sitt sociala konto.

Aktivera kontobekräftelse när en webbplats har användare

Aktivering av kontobekräftelse på en webbplats med användare låser alla befintliga användare. Befintliga användare är utelåst eftersom deras konton inte är bekräftade. Använd någon av följande metoder för att kringgå befintlig användarutelåsning:

  • Uppdatera databasen för att markera alla befintliga användare som bekräftade.
  • Bekräfta befintliga användare. Till exempel batch-skicka e-postmeddelanden med bekräftelselänkar.