Pengantar Identity di ASP.NET Core

IdentityASP.NET Core :

  • Adalah API yang mendukung fungsionalitas login antarmuka pengguna (UI).
  • Mengelola pengguna, kata sandi, data profil, peran, klaim, token, konfirmasi email, dan banyak lagi.

Pengguna dapat membuat akun dengan informasi masuk yang disimpan di Identity atau mereka dapat menggunakan penyedia login eksternal. Penyedia login eksternal yang didukung termasuk Facebook, Google, Akun Microsoft, dan Twitter.

Untuk informasi tentang cara mewajibkan autentikasi untuk semua pengguna aplikasi, lihat Buat aplikasi ASP.NET Core dengan data pengguna yang dilindungi oleh otorisasi.

Kode sumber Identity tersedia di GitHub. Scaffold Identity dan lihat file yang dihasilkan untuk meninjau interaksi templat dengan Identity.

Identity biasanya dikonfigurasi menggunakan database SQL Server untuk menyimpan nama pengguna, kata sandi, dan data profil. Atau, penyimpanan persisten lain seperti Penyimpanan Tabel Azure dapat digunakan.

Dalam topik ini, Anda mempelajari cara menggunakan Identity untuk mendaftar, masuk, dan keluar dari pengguna. Catatan: templat memperlakukan nama pengguna dan email sebagai sama untuk pengguna. Untuk instruksi selengkapnya tentang membuat aplikasi yang menggunakan Identity, lihat Langkah Berikutnya.

Untuk informasi selengkapnya tentang Identity di aplikasi Blazor, lihat autentikasi dan otorisasi ASP.NET Core Blazor dan artikel yang mengikutinya dalam dokumentasi Blazor.

ASP.NET Core Identity tidak terkait dengan platform identitas Microsoft. Platform identitas Microsoft adalah:

  • Evolusi platform pengembang Azure Active Directory (Azure AD).
  • Solusi identitas alternatif untuk autentikasi dan otorisasi di aplikasi ASP.NET Core.

ASP.NET Core Identity menambahkan fungsionalitas login antarmuka pengguna (UI) ke ASP.NET Core web apps. Untuk mengamankan API web dan SPAs, gunakan salah satu hal berikut ini:

Duende Identity Server adalah kerangka kerja OpenID Connect dan OAuth 2.0 untuk ASP.NET Core. Duende Identity Server memungkinkan fitur keamanan berikut:

  • Autentikasi sebagai Layanan (AaaS)
  • Masuk/keluar tunggal (SSO) pada berbagai jenis aplikasi
  • Pengendalian akses untuk API
  • Gateway Federasi

Important

Perangkat Lunak Duende mungkin mengharuskan Anda membayar biaya lisensi untuk penggunaan produksi Server Identity Duende. Untuk informasi selengkapnya, lihat Migrate dari ASP.NET Core di .NET 5 hingga .NET 6.

Untuk informasi selengkapnya, lihat dokumentasi Duende Identity Server (situs web Duende Software).

Tampilkan atau unduh kode sampel (cara mengunduh).

Buat Blazor Web App dengan autentikasi

Buat ASP.NET Core Blazor Web App project dengan Akun Individual.

Note

Razor Pengalaman Pages, lihat bagian Membuat aplikasi Razor Pages dengan autentikasi.

Untuk pengalaman MVC, lihat bagian Membuat aplikasi MVC dengan autentikasi .

  • Blazor Web App Pilih templat. Pilih Selanjutnya.
  • Buat pilihan berikut:
    • Jenis autentikasi: Akun Individual
    • Mode perenderan interaktif: Server
    • Lokasi Interaktivitas: Global
  • Pilih Buat.

project yang dihasilkan mencakup komponen IdentityRazor. Komponen ditemukan di folder Components/Account server project. Contohnya:

  • Components/Account/Pages/Register.razor
  • Components/Account/Pages/Login.razor
  • Components/Account/Pages/Manage/ChangePassword.razor

Identity Razor komponen dijelaskan secara individual dalam dokumentasi untuk kasus penggunaan tertentu dan dapat mengubah setiap rilis. Saat Anda membuat Blazor Web App dengan Akun Individu, komponen IdentityRazor disertakan dalam project yang dihasilkan. Komponen IdentityRazor juga dapat ditemukan dalam folder Components/Account dari proyek server dalam templat proyek Blazor Web App (repositori dotnet/aspnetcore GitHub).

Note

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

Untuk informasi selengkapnya, lihat autentikasi dan otorisasi ASP.NET Core Blazor dan artikel yang mengikutinya dalam dokumentasi Blazor. Sebagian besar artikel di Keamanan dan Identity area dokumentasi ASP.NET Core utama berlaku untuk aplikasi Blazor. Namun, Blazor kumpulan dokumentasi berisi artikel dan panduan yang menggantikan atau menambahkan informasi. Sebaiknya pelajari dokumentasi ASP.NET Core umum yang ditetapkan terlebih dahulu, diikuti dengan mengakses artikel dalam dokumentasi BlazorKeamanan dan Identity.

Buat aplikasi Pages dengan autentikasi

Buat project ASP.NET Core Web Application (Razor Pages) dengan Akun Individual.

  • Pilih templat ASP.NET Core Web App (Razor Pages). Pilih Selanjutnya.
  • Untuk Jenis autentikasi, pilih Akun Individual.
  • Pilih Buat.

project yang dihasilkan menyediakan ASP.NET Core Identity sebagai pustaka kelas Razor (RCL). Identity Razor kelas pustaka mengekspos titik akhir dalam area Identity. Contohnya:

  • Areas/Identity/Pages/Account/Register
  • Areas/Identity/Pages/Account/Login
  • Areas/Identity/Pages/Account/Manage/ChangePassword

Halaman dijelaskan secara terpisah dalam dokumentasi untuk kasus penggunaan tertentu dan dapat berubah setiap kali rilis. Untuk melihat semua halaman di RCL, lihat sumber referensi ASP.NET Core (repositori dotnet/aspnetcore GitHub, folder Identity/UI/src/Areas/Identity/Pages). Anda dapat membuat perancah halaman individual atau semua halaman ke dalam aplikasi. Untuk informasi selengkapnya, lihat Scaffold Identity dalam proyek ASP.NET Core.

Membuat aplikasi MVC dengan autentikasi

Buat project MVC ASP.NET Core dengan Akun Individual.

  • Pilih templat ASP.NET Core Web App (Model-View-Controller). Pilih Selanjutnya.
  • Untuk Jenis autentikasi, pilih Akun Individual.
  • Pilih Buat.

project yang dihasilkan menyediakan ASP.NET Core Identity sebagai pustaka kelas Razor (RCL). Identity Razor Pustaka kelas didasarkan pada Razor Halaman dan menyediakan titik akhir di area Identity. Contohnya:

  • Areas/Identity/Pages/Account/Register
  • Areas/Identity/Pages/Account/Login
  • Areas/Identity/Pages/Account/Manage/ChangePassword

Halaman dijelaskan secara terpisah dalam dokumentasi untuk kasus penggunaan tertentu dan dapat berubah setiap kali rilis. Untuk melihat semua halaman di RCL, lihat sumber referensi ASP.NET Core (repositori dotnet/aspnetcore GitHub, folder Identity/UI/src/Areas/Identity/Pages). Anda dapat membuat perancah halaman individual atau semua halaman ke dalam aplikasi. Untuk informasi selengkapnya, lihat Scaffold Identity dalam proyek ASP.NET Core.

Lakukan penerapan migrasi

Terapkan migrasi untuk menginisialisasi database.

Jalankan perintah berikut di Konsol Package Manager (PMC):

Update-Database

Uji Daftar dan Masuk

Jalankan aplikasi dan daftarkan pengguna. Bergantung pada ukuran layar, Anda mungkin perlu memilih tombol alih navigasi untuk melihat tautan Daftar dan Masuk .

Identity Menampilkan database

  • Dari menu View, pilih SQL Server Object Explorer (SSOX).
  • Navigasi ke (localdb)MSSQLLocalDB(SQL Server 13). Klik kanan pada dbo.AspNetUsers>lihat data:

menu konteks pada tabel AspNetUsers dalam SQL Server Object Explorer

Konfigurasi layanan Identity

Layanan ditambahkan di Program.cs. Pola umumnya adalah memanggil metode dalam urutan berikut:

  1. Add{Service}
  2. builder.Services.Configure{Service}
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebApp1.Data;

var builder = WebApplication.CreateBuilder(args);

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

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

builder.Services.Configure<IdentityOptions>(options =>
{
    // Password settings.
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonAlphanumeric = true;
    options.Password.RequireUppercase = true;
    options.Password.RequiredLength = 6;
    options.Password.RequiredUniqueChars = 1;

    // Lockout settings.
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
    options.Lockout.MaxFailedAccessAttempts = 5;
    options.Lockout.AllowedForNewUsers = true;

    // User settings.
    options.User.AllowedUserNameCharacters =
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
    options.User.RequireUniqueEmail = false;
});

builder.Services.ConfigureApplicationCookie(options =>
{
    // Cookie settings
    options.Cookie.HttpOnly = true;
    options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

    options.LoginPath = "/Identity/Account/Login";
    options.AccessDeniedPath = "/Identity/Account/AccessDenied";
    options.SlidingExpiration = true;
});

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

Kode sebelumnya mengonfigurasi Identity dengan nilai opsi default. Layanan tersedia untuk aplikasi melalui dependency injection.

Identity diaktifkan dengan memanggil UseAuthentication. UseAuthenticationmenambahkan autentikasi middleware ke alur permintaan.

Aplikasi yang dihasilkan templat tidak menggunakan otorisasi. app.UseAuthorization disertakan untuk memastikannya ditambahkan dalam urutan yang benar jika aplikasi menambahkan otorisasi. UseRouting, UseAuthentication, dan UseAuthorization harus dipanggil dalam urutan yang ditunjukkan dalam kode sebelumnya.

Untuk informasi selengkapnya tentang IdentityOptions, lihat IdentityOptions dan Aplikasi Startup.

Metrik ASP.NET Core Identity

metrik ASP.NET Core Identity menyediakan kemampuan pemantauan untuk manajemen pengguna dan proses autentikasi. Metrik ini membantu Anda mendeteksi pola masuk yang tidak biasa yang mungkin menunjukkan ancaman keamanan, melacak performa operasi identitas, dan memahami bagaimana pengguna berinteraksi dengan fitur autentikasi, seperti autentikasi dua faktor. Pengamatan ini sangat berharga untuk aplikasi dengan persyaratan keamanan yang ketat atau yang mengalami lalu lintas autentikasi tinggi.

Untuk detail lengkap tentang metrik yang tersedia dan cara menggunakannya, lihat metrik ASP.NET Core.

Scaffold Pendaftaran, Login, Keluar, dan Konfirmasi Pendaftaran

Tambahkan file Register, Login, LogOut, dan RegisterConfirmation. Ikuti instruksi Scaffold identity dalam Razor project dengan otorisasi untuk menghasilkan kode yang ditampilkan di bagian ini.

Periksa Daftar

Saat pengguna mengklik tombol Daftar di Register halaman, RegisterModel.OnPostAsync tindakan akan dipanggil. Pengguna dibuat oleh CreateAsync(TUser) pada objek _userManager.

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");
    ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
                                          .ToList();
    if (ModelState.IsValid)
    {
        var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
        var result = await _userManager.CreateAsync(user, Input.Password);
        if (result.Succeeded)
        {
            _logger.LogInformation("User created a new account with password.");

            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            var callbackUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = user.Id, code = code },
                protocol: Request.Scheme);

            await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
                $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

            if (_userManager.Options.SignIn.RequireConfirmedAccount)
            {
                return RedirectToPage("RegisterConfirmation", 
                                      new { email = Input.Email });
            }
            else
            {
                await _signInManager.SignInAsync(user, isPersistent: false);
                return LocalRedirect(returnUrl);
            }
        }
        foreach (var error in result.Errors)
        {
            ModelState.AddModelError(string.Empty, error.Description);
        }
    }

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

Menonaktifkan verifikasi akun default

Dengan templat default, 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 di /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs:

[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;
    }

    public string Email { get; set; }

    public bool DisplayConfirmAccountLink { get; set; }

    public string EmailConfirmationUrl { get; set; }

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

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

Masuk

Formulir Masuk ditampilkan saat:

  • Tautan Masuk dipilih.
  • Pengguna mencoba mengakses halaman terbatas yang mereka tidak berwenang untuk mengakses atau jika mereka belum diautentikasi oleh sistem.

Ketika formulir pada halaman Masuk dikirimkan, aksi OnPostAsync dipanggil. PasswordSignInAsync dipanggil pada _signInManager objek .

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");

    if (ModelState.IsValid)
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, 
        // set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(Input.Email,
                           Input.Password, Input.RememberMe, lockoutOnFailure: true);
        if (result.Succeeded)
        {
            _logger.LogInformation("User logged in.");
            return LocalRedirect(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new
            {
                ReturnUrl = returnUrl,
                RememberMe = Input.RememberMe
            });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

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

Untuk informasi tentang cara membuat keputusan otorisasi, lihat Introduksi ke otorisasi di ASP.NET Core.

Keluar

Tautan Keluar menjalankan tindakan LogoutModel.OnPost.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace WebApp1.Areas.Identity.Pages.Account
{
    [AllowAnonymous]
    public class LogoutModel : PageModel
    {
        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly ILogger<LogoutModel> _logger;

        public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
        {
            _signInManager = signInManager;
            _logger = logger;
        }

        public void OnGet()
        {
        }

        public async Task<IActionResult> OnPost(string returnUrl = null)
        {
            await _signInManager.SignOutAsync();
            _logger.LogInformation("User logged out.");
            if (returnUrl != null)
            {
                return LocalRedirect(returnUrl);
            }
            else
            {
                return RedirectToPage();
            }
        }
    }
}

Dalam kode sebelumnya, kode return RedirectToPage(); perlu dialihkan sehingga browser melakukan permintaan baru dan identitas untuk pengguna diperbarui.

SignOutAsync menghapus klaim pengguna yang disimpan dalam cookie.

Postingan ditentukan dalam Pages/Shared/_LoginPartial.cshtml:

@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
    <li class="nav-item">
        <a  class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" 
                                              title="Manage">Hello @User.Identity.Name!</a>
    </li>
    <li class="nav-item">
        <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" 
                                  asp-route-returnUrl="@Url.Page("/", new { area = "" })" 
                                  method="post" >
            <button  type="submit" class="nav-link btn btn-link text-dark">Logout</button>
        </form>
    </li>
}
else
{
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
    </li>
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
}
</ul>

Ujian Identity

Templat proyek web bawaan memungkinkan mengakses halaman beranda secara anonim. Untuk menguji Identity, tambahkan [Authorize]:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

namespace WebApp1.Pages
{
    [Authorize]
    public class PrivacyModel : PageModel
    {
        private readonly ILogger<PrivacyModel> _logger;

        public PrivacyModel(ILogger<PrivacyModel> logger)
        {
            _logger = logger;
        }

        public void OnGet()
        {
        }
    }
}

Jika Anda sedang masuk, silakan keluar. Jalankan aplikasi dan pilih tautan Privacy. Anda diarahkan ke halaman masuk.

Menjelajahi Identity

Untuk menjelajahi Identity secara lebih rinci:

Identity Komponen

Semua paket NuGet yang bergantung pada Identity disertakan dalam framework bersama ASP.NET Core.

Paket utama untuk Identity adalah Microsoft.AspNetCore.Identity. Paket ini berisi serangkaian antarmuka inti untuk ASP.NET Core Identity, dan disertakan oleh Microsoft.AspNetCore.Identity.EntityFrameworkCore.

Bermigrasi ke ASP.NET Core Identity

Untuk informasi dan panduan selengkapnya tentang memigrasikan Identity penyimpanan yang ada, lihat Memigrasikan Autentikasi dan Identity.

Mengatur kekuatan kata sandi

Lihat Konfigurasi untuk sampel yang menetapkan persyaratan kata sandi minimum.

AddDefaultIdentity dan AddIdentity

AddDefaultIdentity diperkenalkan di ASP.NET Core 2.1. Memanggil AddDefaultIdentity mirip dengan memanggil hal-hal berikut ini:

Lihat sumber AddDefaultIdentity untuk informasi selengkapnya.

Mencegah penerbitan aset statis Identity

Untuk mencegah penerbitan aset Identity statis (stylesheet dan file JavaScript untuk antarmuka pengguna Identity) ke akar web, tambahkan properti ResolveStaticWebAssetsInputsDependsOn berikut dan target RemoveIdentityAssets ke file project aplikasi:

<PropertyGroup>
  <ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>

<Target Name="RemoveIdentityAssets">
  <ItemGroup>
    <StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
  </ItemGroup>
</Target>

Langkah Selanjutnya

Oleh Rick Anderson

IdentityASP.NET Core :

  • Adalah API yang mendukung fungsionalitas login antarmuka pengguna (UI).
  • Mengelola pengguna, kata sandi, data profil, peran, klaim, token, konfirmasi email, dan banyak lagi.

Pengguna dapat membuat akun dengan informasi masuk yang disimpan di Identity atau mereka dapat menggunakan penyedia login eksternal. Penyedia login eksternal yang didukung termasuk Facebook, Google, Akun Microsoft, dan Twitter.

Untuk informasi tentang cara mewajibkan autentikasi untuk semua pengguna aplikasi, lihat Buat aplikasi ASP.NET Core dengan data pengguna yang dilindungi oleh otorisasi.

Kode sumber Identity tersedia di GitHub. Scaffold Identity dan lihat file yang dihasilkan untuk meninjau interaksi templat dengan Identity.

Identity biasanya dikonfigurasi menggunakan database SQL Server untuk menyimpan nama pengguna, kata sandi, dan data profil. Atau, penyimpanan persisten lain seperti Penyimpanan Tabel Azure dapat digunakan.

Dalam topik ini, Anda mempelajari cara menggunakan Identity untuk mendaftar, masuk, dan keluar dari pengguna. Catatan: templat memperlakukan nama pengguna dan email sebagai sama untuk pengguna. Untuk instruksi selengkapnya tentang membuat aplikasi yang menggunakan Identity, lihat Langkah Berikutnya.

ASP.NET Core Identity tidak terkait dengan platform identitas Microsoft. Platform identitas Microsoft adalah:

  • Evolusi platform pengembang Azure Active Directory (Azure AD).
  • Solusi identitas alternatif untuk autentikasi dan otorisasi di aplikasi ASP.NET Core.

ASP.NET Core Identity menambahkan fungsionalitas login antarmuka pengguna (UI) ke ASP.NET Core web apps. Untuk mengamankan API web dan SPAs, gunakan salah satu hal berikut ini:

Duende Identity Server adalah kerangka kerja OpenID Connect dan OAuth 2.0 untuk ASP.NET Core. Duende Identity Server memungkinkan fitur keamanan berikut:

  • Autentikasi sebagai Layanan (AaaS)
  • Masuk/keluar tunggal (SSO) pada berbagai jenis aplikasi
  • Pengendalian akses untuk API
  • Gateway Federasi

Important

Perangkat Lunak Duende mungkin mengharuskan Anda membayar biaya lisensi untuk penggunaan produksi Server Identity Duende. Untuk informasi selengkapnya, lihat Migrate dari ASP.NET Core di .NET 5 hingga .NET 6.

Untuk informasi selengkapnya, lihat dokumentasi Duende Identity Server (situs web Duende Software).

Tampilkan atau unduh kode sampel (cara mengunduh).

Membuat aplikasi Web dengan autentikasi

Buat project Aplikasi Web ASP.NET Core dengan Akun Pengguna Individual.

  • Pilih templat ASP.NET Core Web App. Beri nama project WebApp1 untuk memiliki namespace yang sama dengan unduhan project. Klik OK.
  • Pada input Jenis autentikasi, pilih Akun Pengguna Individual.

project yang dihasilkan menyediakan ASP.NET Core Identity sebagai pustaka kelas Razor. Identity Razor kelas pustaka mengekspos titik akhir dalam area Identity. Contohnya:

  • /Identity/Akun/Masuk
  • /Identity/Account/Logout
  • /Identity/Akun/Kelola

Lakukan penerapan migrasi

Terapkan migrasi untuk menginisialisasi database.

Jalankan perintah berikut di Konsol Package Manager (PMC):

Update-Database

Uji Daftar dan Masuk

Jalankan aplikasi dan daftarkan pengguna. Bergantung pada ukuran layar, Anda mungkin perlu memilih tombol alih navigasi untuk melihat tautan Daftar dan Masuk .

Identity Menampilkan database

  • Dari menu View, pilih SQL Server Object Explorer (SSOX).
  • Navigasi ke (localdb)MSSQLLocalDB(SQL Server 13). Klik kanan pada dbo.AspNetUsers>lihat data:

menu konteks pada tabel AspNetUsers dalam SQL Server Object Explorer

Konfigurasi layanan Identity

Layanan ditambahkan di Program.cs. Pola umumnya adalah memanggil metode dalam urutan berikut:

  1. Add{Service}
  2. builder.Services.Configure{Service}
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebApp1.Data;

var builder = WebApplication.CreateBuilder(args);

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

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

builder.Services.Configure<IdentityOptions>(options =>
{
    // Password settings.
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonAlphanumeric = true;
    options.Password.RequireUppercase = true;
    options.Password.RequiredLength = 6;
    options.Password.RequiredUniqueChars = 1;

    // Lockout settings.
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
    options.Lockout.MaxFailedAccessAttempts = 5;
    options.Lockout.AllowedForNewUsers = true;

    // User settings.
    options.User.AllowedUserNameCharacters =
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
    options.User.RequireUniqueEmail = false;
});

builder.Services.ConfigureApplicationCookie(options =>
{
    // Cookie settings
    options.Cookie.HttpOnly = true;
    options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

    options.LoginPath = "/Identity/Account/Login";
    options.AccessDeniedPath = "/Identity/Account/AccessDenied";
    options.SlidingExpiration = true;
});

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

Kode sebelumnya mengonfigurasi Identity dengan nilai opsi default. Layanan tersedia untuk aplikasi melalui dependency injection.

Identity diaktifkan dengan memanggil UseAuthentication. UseAuthenticationmenambahkan autentikasi middleware ke alur permintaan.

Aplikasi yang dihasilkan templat tidak menggunakan otorisasi. app.UseAuthorization disertakan untuk memastikannya ditambahkan dalam urutan yang benar jika aplikasi menambahkan otorisasi. UseRouting, UseAuthentication, dan UseAuthorization harus dipanggil dalam urutan yang ditunjukkan dalam kode sebelumnya.

Untuk informasi selengkapnya tentang IdentityOptions, lihat IdentityOptions dan Aplikasi Startup.

Scaffold Pendaftaran, Login, Keluar, dan Konfirmasi Pendaftaran

Tambahkan file Register, Login, LogOut, dan RegisterConfirmation. Ikuti instruksi Scaffold identity dalam Razor project dengan otorisasi untuk menghasilkan kode yang ditampilkan di bagian ini.

Periksa Daftar

Saat pengguna mengklik tombol Daftar di Register halaman, RegisterModel.OnPostAsync tindakan akan dipanggil. Pengguna dibuat oleh CreateAsync(TUser) pada objek _userManager.

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");
    ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
                                          .ToList();
    if (ModelState.IsValid)
    {
        var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
        var result = await _userManager.CreateAsync(user, Input.Password);
        if (result.Succeeded)
        {
            _logger.LogInformation("User created a new account with password.");

            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            var callbackUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = user.Id, code = code },
                protocol: Request.Scheme);

            await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
                $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

            if (_userManager.Options.SignIn.RequireConfirmedAccount)
            {
                return RedirectToPage("RegisterConfirmation", 
                                      new { email = Input.Email });
            }
            else
            {
                await _signInManager.SignInAsync(user, isPersistent: false);
                return LocalRedirect(returnUrl);
            }
        }
        foreach (var error in result.Errors)
        {
            ModelState.AddModelError(string.Empty, error.Description);
        }
    }

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

Menonaktifkan verifikasi akun default

Dengan templat default, 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 di /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs:

[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;
    }

    public string Email { get; set; }

    public bool DisplayConfirmAccountLink { get; set; }

    public string EmailConfirmationUrl { get; set; }

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

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

Masuk

Formulir Masuk ditampilkan saat:

  • Tautan Masuk dipilih.
  • Pengguna mencoba mengakses halaman terbatas yang mereka tidak berwenang untuk mengakses atau jika mereka belum diautentikasi oleh sistem.

Ketika formulir pada halaman Masuk dikirimkan, aksi OnPostAsync dipanggil. PasswordSignInAsync dipanggil pada _signInManager objek .

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");

    if (ModelState.IsValid)
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, 
        // set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(Input.Email,
                           Input.Password, Input.RememberMe, lockoutOnFailure: true);
        if (result.Succeeded)
        {
            _logger.LogInformation("User logged in.");
            return LocalRedirect(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new
            {
                ReturnUrl = returnUrl,
                RememberMe = Input.RememberMe
            });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

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

Untuk informasi tentang cara membuat keputusan otorisasi, lihat Introduksi ke otorisasi di ASP.NET Core.

Keluar

Tautan Keluar menjalankan tindakan LogoutModel.OnPost.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace WebApp1.Areas.Identity.Pages.Account
{
    [AllowAnonymous]
    public class LogoutModel : PageModel
    {
        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly ILogger<LogoutModel> _logger;

        public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
        {
            _signInManager = signInManager;
            _logger = logger;
        }

        public void OnGet()
        {
        }

        public async Task<IActionResult> OnPost(string returnUrl = null)
        {
            await _signInManager.SignOutAsync();
            _logger.LogInformation("User logged out.");
            if (returnUrl != null)
            {
                return LocalRedirect(returnUrl);
            }
            else
            {
                return RedirectToPage();
            }
        }
    }
}

Dalam kode sebelumnya, kode return RedirectToPage(); perlu dialihkan sehingga browser melakukan permintaan baru dan identitas untuk pengguna diperbarui.

SignOutAsync menghapus klaim pengguna yang disimpan dalam cookie.

Postingan ditentukan dalam Pages/Shared/_LoginPartial.cshtml:

@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
    <li class="nav-item">
        <a  class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" 
                                              title="Manage">Hello @User.Identity.Name!</a>
    </li>
    <li class="nav-item">
        <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" 
                                  asp-route-returnUrl="@Url.Page("/", new { area = "" })" 
                                  method="post" >
            <button  type="submit" class="nav-link btn btn-link text-dark">Logout</button>
        </form>
    </li>
}
else
{
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
    </li>
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
}
</ul>

Ujian Identity

Templat proyek web bawaan memungkinkan mengakses halaman beranda secara anonim. Untuk menguji Identity, tambahkan [Authorize]:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

namespace WebApp1.Pages
{
    [Authorize]
    public class PrivacyModel : PageModel
    {
        private readonly ILogger<PrivacyModel> _logger;

        public PrivacyModel(ILogger<PrivacyModel> logger)
        {
            _logger = logger;
        }

        public void OnGet()
        {
        }
    }
}

Jika Anda sedang masuk, silakan keluar. Jalankan aplikasi dan pilih tautan Privacy. Anda diarahkan ke halaman masuk.

Menjelajahi Identity

Untuk menjelajahi Identity secara lebih rinci:

Identity Komponen

Semua paket NuGet yang bergantung pada Identity disertakan dalam framework bersama ASP.NET Core.

Paket utama untuk Identity adalah Microsoft.AspNetCore.Identity. Paket ini berisi serangkaian antarmuka inti untuk ASP.NET Core Identity, dan disertakan oleh Microsoft.AspNetCore.Identity.EntityFrameworkCore.

Bermigrasi ke ASP.NET Core Identity

Untuk informasi dan panduan selengkapnya tentang memigrasikan Identity penyimpanan yang ada, lihat Memigrasikan Autentikasi dan Identity.

Mengatur kekuatan kata sandi

Lihat Konfigurasi untuk sampel yang menetapkan persyaratan kata sandi minimum.

AddDefaultIdentity dan AddIdentity

AddDefaultIdentity diperkenalkan di ASP.NET Core 2.1. Memanggil AddDefaultIdentity mirip dengan memanggil hal-hal berikut ini:

Lihat sumber AddDefaultIdentity untuk informasi selengkapnya.

Mencegah penerbitan aset statis Identity

Untuk mencegah penerbitan aset Identity statis (stylesheet dan file JavaScript untuk antarmuka pengguna Identity) ke akar web, tambahkan properti ResolveStaticWebAssetsInputsDependsOn berikut dan target RemoveIdentityAssets ke file project aplikasi:

<PropertyGroup>
  <ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>

<Target Name="RemoveIdentityAssets">
  <ItemGroup>
    <StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
  </ItemGroup>
</Target>

Langkah Selanjutnya

Oleh Rick Anderson

IdentityASP.NET Core :

  • Adalah API yang mendukung fungsionalitas login antarmuka pengguna (UI).
  • Mengelola pengguna, kata sandi, data profil, peran, klaim, token, konfirmasi email, dan banyak lagi.

Pengguna dapat membuat akun dengan informasi masuk yang disimpan di Identity atau mereka dapat menggunakan penyedia login eksternal. Penyedia login eksternal yang didukung termasuk Facebook, Google, Akun Microsoft, dan Twitter.

Untuk informasi tentang cara mewajibkan autentikasi untuk semua pengguna aplikasi, lihat Buat aplikasi ASP.NET Core dengan data pengguna yang dilindungi oleh otorisasi.

Kode sumber Identity tersedia di GitHub. Scaffold Identity dan lihat file yang dihasilkan untuk meninjau interaksi templat dengan Identity.

Identity biasanya dikonfigurasi menggunakan database SQL Server untuk menyimpan nama pengguna, kata sandi, dan data profil. Atau, penyimpanan persisten lain seperti Penyimpanan Tabel Azure dapat digunakan.

Dalam topik ini, Anda mempelajari cara menggunakan Identity untuk mendaftar, masuk, dan keluar dari pengguna. Catatan: templat memperlakukan nama pengguna dan email sebagai sama untuk pengguna. Untuk instruksi selengkapnya tentang membuat aplikasi yang menggunakan Identity, lihat Langkah Berikutnya.

Platform identitasMicrosoft adalah:

  • Evolusi platform pengembang Azure Active Directory (Azure AD).
  • Solusi identitas alternatif untuk autentikasi dan otorisasi di aplikasi ASP.NET Core.
  • Tidak terkait dengan ASP.NET Core Identity.

ASP.NET Core Identity menambahkan fungsionalitas login antarmuka pengguna (UI) ke ASP.NET Core web apps. Untuk mengamankan API web dan SPAs, gunakan salah satu hal berikut ini:

Duende IdentityServer adalah kerangka kerja OpenID Connect dan OAuth 2.0 untuk ASP.NET Core. Duende IdentityServer memungkinkan fitur keamanan berikut:

  • Autentikasi sebagai Layanan (AaaS)
  • Masuk/keluar tunggal (SSO) pada berbagai jenis aplikasi
  • Pengendalian akses untuk API
  • Gateway Federasi

Untuk informasi selengkapnya, lihat Gambaran Umum Duende IdentityServer.

Untuk informasi selengkapnya tentang penyedia autentikasi lainnya, lihat opsi autentikasi OSS Komunitas untuk ASP.NET Core

Tampilkan atau unduh kode sampel (cara mengunduh).

Membuat aplikasi Web dengan autentikasi

Buat project Aplikasi Web ASP.NET Core dengan Akun Pengguna Individual.

  • Pilih File>Baru>Proyek.
  • Pilih ASP.NET Core Aplikasi Web. Beri nama project WebApp1 untuk memiliki namespace yang sama dengan unduhan project. Klik OK.
  • Pilih aplikasi ASP.NET Core Web, lalu pilih Ubah Autentikasi.
  • Pilih Akun Pengguna Individual dan klik OK.

project yang dihasilkan menyediakan ASP.NET Core Identity sebagai pustaka kelas Razor. Identity Razor kelas pustaka mengekspos titik akhir dalam area Identity. Contohnya:

  • /Identity/Akun/Masuk
  • /Identity/Account/Logout
  • /Identity/Akun/Kelola

Lakukan penerapan migrasi

Terapkan migrasi untuk menginisialisasi database.

Jalankan perintah berikut di Konsol Package Manager (PMC):

PM> Update-Database

Uji Daftar dan Masuk

Jalankan aplikasi dan daftarkan pengguna. Bergantung pada ukuran layar, Anda mungkin perlu memilih tombol alih navigasi untuk melihat tautan Daftar dan Masuk .

Identity Menampilkan database

  • Dari menu View, pilih SQL Server Object Explorer (SSOX).
  • Navigasi ke (localdb)MSSQLLocalDB(SQL Server 13). Klik kanan pada dbo.AspNetUsers>lihat data:

menu konteks pada tabel AspNetUsers dalam SQL Server Object Explorer

Konfigurasi layanan Identity

Layanan ditambahkan di ConfigureServices. Pola umumnya adalah memanggil semua Add{Service} metode, lalu memanggil semua services.Configure{Service} metode.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
     // options.UseSqlite(
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();
    services.AddRazorPages();

    services.Configure<IdentityOptions>(options =>
    {
        // Password settings.
        options.Password.RequireDigit = true;
        options.Password.RequireLowercase = true;
        options.Password.RequireNonAlphanumeric = true;
        options.Password.RequireUppercase = true;
        options.Password.RequiredLength = 6;
        options.Password.RequiredUniqueChars = 1;

        // Lockout settings.
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
        options.Lockout.MaxFailedAccessAttempts = 5;
        options.Lockout.AllowedForNewUsers = true;

        // User settings.
        options.User.AllowedUserNameCharacters =
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
        options.User.RequireUniqueEmail = false;
    });

    services.ConfigureApplicationCookie(options =>
    {
        // Cookie settings
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

        options.LoginPath = "/Identity/Account/Login";
        options.AccessDeniedPath = "/Identity/Account/AccessDenied";
        options.SlidingExpiration = true;
    });
}

Kode yang disorot sebelumnya Identity dikonfigurasi dengan nilai opsi default. Layanan tersedia untuk aplikasi melalui dependency injection.

Identity diaktifkan dengan memanggil UseAuthentication. UseAuthenticationmenambahkan autentikasi middleware ke alur permintaan.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

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

    app.UseRouting();

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

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        // options.UseSqlite(
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDatabaseDeveloperPageExceptionFilter();
    services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();
    services.AddRazorPages();

    services.Configure<IdentityOptions>(options =>
    {
        // Password settings.
        options.Password.RequireDigit = true;
        options.Password.RequireLowercase = true;
        options.Password.RequireNonAlphanumeric = true;
        options.Password.RequireUppercase = true;
        options.Password.RequiredLength = 6;
        options.Password.RequiredUniqueChars = 1;

        // Lockout settings.
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
        options.Lockout.MaxFailedAccessAttempts = 5;
        options.Lockout.AllowedForNewUsers = true;

        // User settings.
        options.User.AllowedUserNameCharacters =
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
        options.User.RequireUniqueEmail = false;
    });

    services.ConfigureApplicationCookie(options =>
    {
        // Cookie settings
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

        options.LoginPath = "/Identity/Account/Login";
        options.AccessDeniedPath = "/Identity/Account/AccessDenied";
        options.SlidingExpiration = true;
    });
}

Kode sebelumnya mengonfigurasi Identity dengan nilai opsi default. Layanan tersedia untuk aplikasi melalui dependency injection.

Identity diaktifkan dengan memanggil UseAuthentication. UseAuthenticationmenambahkan autentikasi middleware ke alur permintaan.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseMigrationsEndPoint();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

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

    app.UseRouting();

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

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

Aplikasi yang dihasilkan templat tidak menggunakan otorisasi. app.UseAuthorization disertakan untuk memastikannya ditambahkan dalam urutan yang benar jika aplikasi menambahkan otorisasi. UseRouting, , UseAuthenticationUseAuthorization, dan UseEndpoints harus dipanggil dalam urutan yang ditunjukkan dalam kode sebelumnya.

Untuk informasi selengkapnya tentang IdentityOptions dan Startup, lihat IdentityOptions dan Pemulaan Aplikasi.

Scaffold Pendaftaran, Login, Keluar, dan Konfirmasi Pendaftaran

Tambahkan file Register, Login, LogOut, dan RegisterConfirmation. Ikuti instruksi Scaffold identity dalam Razor project dengan otorisasi untuk menghasilkan kode yang ditampilkan di bagian ini.

Periksa Daftar

Saat pengguna mengklik tombol Daftar di Register halaman, RegisterModel.OnPostAsync tindakan akan dipanggil. Pengguna dibuat oleh CreateAsync(TUser) pada objek _userManager.

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");
    ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
                                          .ToList();
    if (ModelState.IsValid)
    {
        var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
        var result = await _userManager.CreateAsync(user, Input.Password);
        if (result.Succeeded)
        {
            _logger.LogInformation("User created a new account with password.");

            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            var callbackUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = user.Id, code = code },
                protocol: Request.Scheme);

            await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
                $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

            if (_userManager.Options.SignIn.RequireConfirmedAccount)
            {
                return RedirectToPage("RegisterConfirmation", 
                                      new { email = Input.Email });
            }
            else
            {
                await _signInManager.SignInAsync(user, isPersistent: false);
                return LocalRedirect(returnUrl);
            }
        }
        foreach (var error in result.Errors)
        {
            ModelState.AddModelError(string.Empty, error.Description);
        }
    }

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

Menonaktifkan verifikasi akun default

Dengan templat default, 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 di /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs:

[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;
    }

    public string Email { get; set; }

    public bool DisplayConfirmAccountLink { get; set; }

    public string EmailConfirmationUrl { get; set; }

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

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

Masuk

Formulir Masuk ditampilkan saat:

  • Tautan Masuk dipilih.
  • Pengguna mencoba mengakses halaman terbatas yang mereka tidak berwenang untuk mengakses atau jika mereka belum diautentikasi oleh sistem.

Ketika formulir pada halaman Masuk dikirimkan, aksi OnPostAsync dipanggil. PasswordSignInAsync dipanggil pada _signInManager objek .

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");

    if (ModelState.IsValid)
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, 
        // set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(Input.Email,
                           Input.Password, Input.RememberMe, lockoutOnFailure: true);
        if (result.Succeeded)
        {
            _logger.LogInformation("User logged in.");
            return LocalRedirect(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new
            {
                ReturnUrl = returnUrl,
                RememberMe = Input.RememberMe
            });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

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

Untuk informasi tentang cara membuat keputusan otorisasi, lihat Introduksi ke otorisasi di ASP.NET Core.

Keluar

Tautan Keluar menjalankan tindakan LogoutModel.OnPost.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace WebApp1.Areas.Identity.Pages.Account
{
    [AllowAnonymous]
    public class LogoutModel : PageModel
    {
        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly ILogger<LogoutModel> _logger;

        public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
        {
            _signInManager = signInManager;
            _logger = logger;
        }

        public void OnGet()
        {
        }

        public async Task<IActionResult> OnPost(string returnUrl = null)
        {
            await _signInManager.SignOutAsync();
            _logger.LogInformation("User logged out.");
            if (returnUrl != null)
            {
                return LocalRedirect(returnUrl);
            }
            else
            {
                return RedirectToPage();
            }
        }
    }
}

Dalam kode sebelumnya, kode return RedirectToPage(); perlu dialihkan sehingga browser melakukan permintaan baru dan identitas untuk pengguna diperbarui.

SignOutAsync menghapus klaim pengguna yang disimpan dalam cookie.

Postingan ditentukan dalam Pages/Shared/_LoginPartial.cshtml:

@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
    <li class="nav-item">
        <a  class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" 
                                              title="Manage">Hello @User.Identity.Name!</a>
    </li>
    <li class="nav-item">
        <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" 
                                  asp-route-returnUrl="@Url.Page("/", new { area = "" })" 
                                  method="post" >
            <button  type="submit" class="nav-link btn btn-link text-dark">Logout</button>
        </form>
    </li>
}
else
{
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
    </li>
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
}
</ul>

Ujian Identity

Templat proyek web bawaan memungkinkan mengakses halaman beranda secara anonim. Untuk menguji Identity, tambahkan [Authorize]:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

namespace WebApp1.Pages
{
    [Authorize]
    public class PrivacyModel : PageModel
    {
        private readonly ILogger<PrivacyModel> _logger;

        public PrivacyModel(ILogger<PrivacyModel> logger)
        {
            _logger = logger;
        }

        public void OnGet()
        {
        }
    }
}

Jika Anda sedang masuk, silakan keluar. Jalankan aplikasi dan pilih tautan Privacy. Anda diarahkan ke halaman masuk.

Menjelajahi Identity

Untuk menjelajahi Identity secara lebih rinci:

Identity Komponen

Semua paket NuGet yang bergantung pada Identity disertakan dalam framework bersama ASP.NET Core.

Paket utama untuk Identity adalah Microsoft.AspNetCore.Identity. Paket ini berisi serangkaian antarmuka inti untuk ASP.NET Core Identity, dan disertakan oleh Microsoft.AspNetCore.Identity.EntityFrameworkCore.

Bermigrasi ke ASP.NET Core Identity

Untuk informasi dan panduan selengkapnya tentang memigrasikan Identity penyimpanan yang ada, lihat Memigrasikan Autentikasi dan Identity.

Mengatur kekuatan kata sandi

Lihat Konfigurasi untuk sampel yang menetapkan persyaratan kata sandi minimum.

Mencegah penerbitan aset statis Identity

Untuk mencegah penerbitan aset Identity statis (stylesheet dan file JavaScript untuk antarmuka pengguna Identity) ke akar web, tambahkan properti ResolveStaticWebAssetsInputsDependsOn berikut dan target RemoveIdentityAssets ke file project aplikasi:

<PropertyGroup>
  <ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>

<Target Name="RemoveIdentityAssets">
  <ItemGroup>
    <StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
  </ItemGroup>
</Target>

Langkah Selanjutnya