Konfirmasi akun dan pemulihan kata sandi di ASP.NET Core

Oleh Rick Anderson, Ponant, dan Joe Audette

Tutorial ini menunjukkan cara membuat aplikasi ASP.NET Core dengan konfirmasi email dan pengaturan ulang kata sandi. Tutorial ini bukan topik awal. Anda harus memiliki pemahaman terkait:

Prasyarat

Membuat dan menguji aplikasi web dengan autentikasi

Jalankan perintah berikut untuk membuat aplikasi web dengan autentikasi.

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

Mendaftarkan pengguna dengan konfirmasi email yang disimulasikan

Jalankan aplikasi, pilih tautan Daftar , dan daftarkan pengguna. Setelah terdaftar, Anda diarahkan ke /Identity/Account/RegisterConfirmation halaman yang berisi tautan untuk mensimulasikan konfirmasi email:

  • Pilih tautan Click here to confirm your account.
  • Pilih tautan Masuk dan masuk dengan kredensial yang sama.
  • Hello YourEmail@provider.com! Pilih tautan, yang mengalihkan ke /Identity/Account/Manage/PersonalData halaman.
  • Pilih tab Data pribadi di sebelah kiri, lalu pilih Hapus.

Tautan Click here to confirm your account ditampilkan karena IEmailSender belum diimplementasikan dan terdaftar dengan kontainer injeksi dependensi. Lihat sumbernyaRegisterConfirmation.

Catatan

Tautan dokumentasi ke sumber referensi .NET biasanya memuat cabang default repositori, yang mewakili pengembangan saat ini untuk rilis .NET berikutnya. Untuk memilih tag rilis tertentu, gunakan daftar dropdown Beralih cabang atau tag. Untuk informasi lebih lanjut, lihat Cara memilih tag versi kode sumber ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Mengonfigurasi penyedia email

Dalam tutorial ini, SendGrid digunakan untuk mengirim email. Akun dan kunci SendGrid diperlukan untuk mengirim email. Sebaiknya gunakan SendGrid atau layanan email lain untuk mengirim email daripada SMTP. SMTP sulit diamankan dan disiapkan dengan benar.

Akun SendGrid mungkin memerlukan penambahan Pengirim.

Buat kelas untuk mengambil kunci email aman. Untuk sampel ini, buat Services/AuthMessageSenderOptions.cs:

namespace WebPWrecover.Services;

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

Mengonfigurasi rahasia pengguna SendGrid

Atur SendGridKey dengan alat secret-manager. Misalnya:

dotnet user-secrets set SendGridKey <key>

Successfully saved SendGridKey to the secret store.

Di Windows, Secret Manager menyimpan pasangan kunci/nilai dalam secrets.json file di %APPDATA%/Microsoft/UserSecrets/<WebAppName-userSecretsId> direktori.

Konten secrets.json file tidak dienkripsi. Markup berikut menunjukkan secrets.json file . Nilai SendGridKey telah dihapus.

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

Untuk informasi selengkapnya, lihat pola dan konfigurasi Opsi.

Menginstal SendGrid

Tutorial ini menunjukkan cara menambahkan pemberitahuan email melalui SendGrid, tetapi penyedia email lain dapat digunakan.

SendGrid Instal paket NuGet:

Dari Konsol Manajer Paket, masukkan perintah berikut:

Install-Package SendGrid

Lihat Mulai menggunakan SendGrid secara Gratis untuk mendaftar akun SendGrid gratis.

Menerapkan IEmailSender

Untuk Menerapkan IEmailSender, buat Services/EmailSender.cs dengan kode yang mirip dengan yang berikut ini:

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

Mengonfigurasi aplikasi untuk mendukung email

Tambahkan kode berikut ke file Program.cs:

  • Tambahkan EmailSender sebagai layanan sementara.
  • Daftarkan AuthMessageSenderOptions instans konfigurasi.
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();

Nonaktifkan verifikasi akun default saat Account.RegisterConfirmation telah di-scaffold

Bagian ini hanya berlaku ketika Account.RegisterConfirmation perancah. Lewati bagian ini jika Anda belum membuat perancah Account.RegisterConfirmation.

Pengguna dialihkan ke Account.RegisterConfirmation tempat mereka dapat memilih tautan untuk mengonfirmasi akun. Default Account.RegisterConfirmation hanya digunakan untuk pengujian, verifikasi akun otomatis harus dinonaktifkan di aplikasi produksi.

Untuk memerlukan akun yang dikonfirmasi dan mencegah masuk segera saat pendaftaran, atur DisplayConfirmAccountLink = false dalam file perancah /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();
        }
    }
}

Langkah ini hanya diperlukan ketika Account.RegisterConfirmation di-scaffold. RegisterConfirmation yang tidak di-scaffold secara otomatis mendeteksi kapan IEmailSender telah diimplementasikan dan terdaftar dengan kontainer injeksi dependensi.

Mendaftar, mengonfirmasi email, dan mengatur ulang kata sandi

Jalankan aplikasi web, dan uji konfirmasi akun dan alur pemulihan kata sandi.

  • Jalankan aplikasi dan daftarkan pengguna baru
  • Periksa email Anda untuk tautan konfirmasi akun. Lihat Men-debug email jika Anda tidak mendapatkan email.
  • Klik tautan untuk mengonfirmasi email Anda.
  • Masuk dengan email dan kata sandi Anda.
  • Keluar.

Menguji pengaturan ulang kata sandi

  • Jika Anda masuk, pilih Keluar.
  • Pilih tautan Masuk dan pilih tautan Lupa kata sandi Anda?
  • Masukkan email yang Anda gunakan untuk mendaftarkan akun.
  • Email dengan tautan untuk mengatur ulang kata sandi Anda dikirim. Periksa email Anda dan klik tautan untuk mengatur ulang kata sandi Anda. Setelah kata sandi berhasil direset, Anda dapat masuk dengan email dan kata sandi baru Anda.

Kirim ulang konfirmasi email

Pilih tautan Kirim ulang konfirmasi email di halaman Masuk .

Mengubah email dan batas waktu aktivitas

Batas waktu tidak aktif default adalah 14 hari. Kode berikut mengatur batas waktu tidak aktif menjadi 5 hari:

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

Mengubah semua masa pakai token perlindungan data

Kode berikut mengubah semua periode batas waktu token perlindungan data menjadi 3 jam:

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.

Token pengguna bawaan Identity (lihat AspNetCore/src/Identity/Extensions.Core/src/TokenOptions.cs )memiliki batas waktu satu hari.

Mengubah masa pakai token email

Masa pakai token default token Identity pengguna adalah satu hari. Bagian ini memperlihatkan cara mengubah masa pakai token email.

Tambahkan kustom DataProtectorTokenProvider<TUser> dan 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);
    }
}

Tambahkan penyedia kustom ke kontainer layanan:

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.

Debug email

Jika Anda tidak bisa membuat email berfungsi:

  • Atur titik henti untuk EmailSender.Execute memverifikasi SendGridClient.SendEmailAsync dipanggil.
  • Buat aplikasi konsol untuk mengirim email menggunakan kode serupa dengan EmailSender.Execute.
  • Tinjau halaman Aktivitas Email.
  • Periksa folder spam Anda.
  • Coba alias email lain di penyedia email lain (Microsoft, Yahoo, Gmail, dll.)
  • Coba kirim ke akun email yang berbeda.

Praktik terbaik keamanan adalah tidak menggunakan rahasia produksi dalam pengujian dan pengembangan. Jika Anda menerbitkan aplikasi ke Azure, atur rahasia SendGrid sebagai pengaturan aplikasi di portal Azure Web App. Sistem konfigurasi disiapkan untuk membaca kunci dari variabel lingkungan.

Menggabungkan akun masuk sosial dan lokal

Untuk menyelesaikan bagian ini, Anda harus terlebih dahulu mengaktifkan penyedia autentikasi eksternal. Lihat Facebook, Google, dan autentikasi penyedia eksternal.

Anda dapat menggabungkan akun lokal dan sosial dengan mengklik tautan email Anda. Dalam urutan berikut, "RickAndMSFT@gmail.com" pertama kali dibuat sebagai login lokal; namun, Anda dapat membuat akun sebagai login sosial terlebih dahulu, lalu menambahkan login lokal.

Web application: RickAndMSFT@gmail.com user authenticated

Klik tautan Kelola . Perhatikan 0 eksternal (login sosial) yang terkait dengan akun ini.

Manage view

Klik tautan ke layanan masuk lain dan terima permintaan aplikasi. Dalam gambar berikut, Facebook adalah penyedia autentikasi eksternal:

Manage your external logins view listing Facebook

Kedua akun telah digabungkan. Anda dapat masuk dengan salah satu akun. Anda mungkin ingin pengguna Anda menambahkan akun lokal jika layanan autentikasi masuk sosial mereka tidak berfungsi, atau kemungkinan besar mereka telah kehilangan akses ke akun sosial mereka.

Mengaktifkan konfirmasi akun setelah situs memiliki pengguna

Mengaktifkan konfirmasi akun di situs dengan pengguna mengunci semua pengguna yang ada. Pengguna yang ada dikunci karena akun mereka tidak dikonfirmasi. Untuk mengatasi penguncian pengguna yang ada, gunakan salah satu pendekatan berikut:

  • Perbarui database untuk menandai semua pengguna yang sudah ada sebagai dikonfirmasi.
  • Mengonfirmasi pengguna yang sudah ada. Misalnya, email kirim batch dengan tautan konfirmasi.

Prasyarat

.NET Core 3.0 SDK atau yang lebih baru

Membuat dan menguji aplikasi web dengan autentikasi

Jalankan perintah berikut untuk membuat aplikasi web dengan autentikasi.

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

Jalankan aplikasi, pilih tautan Daftar , dan daftarkan pengguna. Setelah terdaftar, Anda diarahkan ke /Identity/Account/RegisterConfirmation halaman yang berisi tautan untuk mensimulasikan konfirmasi email:

  • Pilih tautan Click here to confirm your account.
  • Pilih tautan Masuk dan masuk dengan kredensial yang sama.
  • Hello YourEmail@provider.com! Pilih tautan, yang mengarahkan Anda ke /Identity/Account/Manage/PersonalData halaman.
  • Pilih tab Data pribadi di sebelah kiri, lalu pilih Hapus.

Mengonfigurasi penyedia email

Dalam tutorial ini, SendGrid digunakan untuk mengirim email. Anda dapat menggunakan penyedia email lain. Sebaiknya gunakan SendGrid atau layanan email lain untuk mengirim email. SMTP sulit dikonfigurasi sehingga email tidak ditandai sebagai spam.

Akun SendGrid mungkin memerlukan penambahan Pengirim.

Buat kelas untuk mengambil kunci email aman. Untuk sampel ini, buat Services/AuthMessageSenderOptions.cs:

namespace WebPWrecover.Services;

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

Mengonfigurasi rahasia pengguna SendGrid

Atur SendGridKey dengan alat secret-manager. Misalnya:

dotnet user-secrets set SendGridKey <SG.key>

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

Di Windows, Secret Manager menyimpan pasangan kunci/nilai dalam secrets.json file di %APPDATA%/Microsoft/UserSecrets/<WebAppName-userSecretsId> direktori.

Konten secrets.json file tidak dienkripsi. Markup berikut menunjukkan secrets.json file . Nilai SendGridKey telah dihapus.

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

Untuk informasi selengkapnya, lihat pola dan konfigurasi Opsi.

Menginstal SendGrid

Tutorial ini menunjukkan cara menambahkan pemberitahuan email melalui SendGrid, tetapi Anda dapat mengirim email menggunakan SMTP dan mekanisme lainnya.

SendGrid Instal paket NuGet:

Dari Konsol Manajer Paket, masukkan perintah berikut:

Install-Package SendGrid

Lihat Mulai menggunakan SendGrid secara Gratis untuk mendaftar akun SendGrid gratis.

Menerapkan IEmailSender

Untuk Menerapkan IEmailSender, buat Services/EmailSender.cs dengan kode yang mirip dengan yang berikut ini:

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

Mengonfigurasi startup untuk mendukung email

Tambahkan kode berikut ke ConfigureServices metode dalam Startup.cs file:

  • Tambahkan EmailSender sebagai layanan sementara.
  • Daftarkan AuthMessageSenderOptions instans konfigurasi.
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();

Scaffold RegisterConfirmation

Ikuti instruksi untuk Perancah Identity dan perancah Account\RegisterConfirmation.

Nonaktifkan verifikasi akun default saat Account.RegisterConfirmation telah di-scaffold

Bagian ini hanya berlaku ketika Account.RegisterConfirmation perancah. Lewati bagian ini jika Anda belum membuat perancah Account.RegisterConfirmation.

Pengguna dialihkan ke Account.RegisterConfirmation tempat mereka dapat memilih tautan untuk mengonfirmasi akun. Default Account.RegisterConfirmation hanya digunakan untuk pengujian, verifikasi akun otomatis harus dinonaktifkan di aplikasi produksi.

Untuk memerlukan akun yang dikonfirmasi dan mencegah masuk segera saat pendaftaran, atur DisplayConfirmAccountLink = false dalam file perancah /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();
        }
    }
}

Langkah ini hanya diperlukan ketika Account.RegisterConfirmation di-scaffold. RegisterConfirmation yang tidak di-scaffold secara otomatis mendeteksi kapan IEmailSender telah diimplementasikan dan terdaftar dengan kontainer injeksi dependensi.

Mendaftar, mengonfirmasi email, dan mengatur ulang kata sandi

Jalankan aplikasi web, dan uji konfirmasi akun dan alur pemulihan kata sandi.

  • Jalankan aplikasi dan daftarkan pengguna baru
  • Periksa email Anda untuk tautan konfirmasi akun. Lihat Men-debug email jika Anda tidak mendapatkan email.
  • Klik tautan untuk mengonfirmasi email Anda.
  • Masuk dengan email dan kata sandi Anda.
  • Keluar.

Menguji pengaturan ulang kata sandi

  • Jika Anda masuk, pilih Keluar.
  • Pilih tautan Masuk dan pilih tautan Lupa kata sandi Anda?
  • Masukkan email yang Anda gunakan untuk mendaftarkan akun.
  • Email dengan tautan untuk mengatur ulang kata sandi Anda dikirim. Periksa email Anda dan klik tautan untuk mengatur ulang kata sandi Anda. Setelah kata sandi berhasil direset, Anda dapat masuk dengan email dan kata sandi baru Anda.

Kirim ulang konfirmasi email

Di ASP.NET Core 5.0 dan yang lebih baru, pilih tautan Kirim ulang konfirmasi email di halaman Masuk .

Mengubah email dan batas waktu aktivitas

Batas waktu tidak aktif default adalah 14 hari. Kode berikut mengatur batas waktu tidak aktif menjadi 5 hari:

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

Mengubah semua masa pakai token perlindungan data

Kode berikut mengubah semua periode batas waktu token perlindungan data menjadi 3 jam:

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

Token pengguna bawaan Identity (lihat AspNetCore/src/Identity/Extensions.Core/src/TokenOptions.cs )memiliki batas waktu satu hari.

Mengubah masa pakai token email

Masa pakai token default token Identity pengguna adalah satu hari. Bagian ini memperlihatkan cara mengubah masa pakai token email.

Tambahkan kustom DataProtectorTokenProvider<TUser> dan 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);
    }
}

Tambahkan penyedia kustom ke kontainer layanan:

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

Debug email

Jika Anda tidak bisa membuat email berfungsi:

  • Atur titik henti untuk EmailSender.Execute memverifikasi SendGridClient.SendEmailAsync dipanggil.
  • Buat aplikasi konsol untuk mengirim email menggunakan kode serupa dengan EmailSender.Execute.
  • Tinjau halaman Aktivitas Email.
  • Periksa folder spam Anda.
  • Coba alias email lain di penyedia email lain (Microsoft, Yahoo, Gmail, dll.)
  • Coba kirim ke akun email yang berbeda.

Praktik terbaik keamanan adalah tidak menggunakan rahasia produksi dalam pengujian dan pengembangan. Jika Anda menerbitkan aplikasi ke Azure, atur rahasia SendGrid sebagai pengaturan aplikasi di portal Azure Web App. Sistem konfigurasi disiapkan untuk membaca kunci dari variabel lingkungan.

Menggabungkan akun masuk sosial dan lokal

Untuk menyelesaikan bagian ini, Anda harus terlebih dahulu mengaktifkan penyedia autentikasi eksternal. Lihat Facebook, Google, dan autentikasi penyedia eksternal.

Anda dapat menggabungkan akun lokal dan sosial dengan mengklik tautan email Anda. Dalam urutan berikut, "RickAndMSFT@gmail.com" pertama kali dibuat sebagai login lokal; namun, Anda dapat membuat akun sebagai login sosial terlebih dahulu, lalu menambahkan login lokal.

Web application: RickAndMSFT@gmail.com user authenticated

Klik tautan Kelola . Perhatikan 0 eksternal (login sosial) yang terkait dengan akun ini.

Manage view

Klik tautan ke layanan masuk lain dan terima permintaan aplikasi. Dalam gambar berikut, Facebook adalah penyedia autentikasi eksternal:

Manage your external logins view listing Facebook

Kedua akun telah digabungkan. Anda dapat masuk dengan salah satu akun. Anda mungkin ingin pengguna Anda menambahkan akun lokal jika layanan autentikasi masuk sosial mereka tidak berfungsi, atau kemungkinan besar mereka telah kehilangan akses ke akun sosial mereka.

Mengaktifkan konfirmasi akun setelah situs memiliki pengguna

Mengaktifkan konfirmasi akun di situs dengan pengguna mengunci semua pengguna yang ada. Pengguna yang ada dikunci karena akun mereka tidak dikonfirmasi. Untuk mengatasi penguncian pengguna yang ada, gunakan salah satu pendekatan berikut:

  • Perbarui database untuk menandai semua pengguna yang sudah ada sebagai dikonfirmasi.
  • Mengonfirmasi pengguna yang sudah ada. Misalnya, email kirim batch dengan tautan konfirmasi.