Pengantar Identity ASP.NET Core
Oleh Rick Anderson
ASP.NET Core Identity:
- 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 atau Identity mereka dapat menggunakan penyedia login eksternal. Penyedia login eksternal yang didukung termasuk Facebook, Google, Akun Microsoft, dan Twitter.
Untuk informasi tentang cara mengharuskan semua pengguna diautentikasi secara global, lihat Memerlukan pengguna yang diautentikasi.
Kode Identity sumber tersedia di GitHub. Perancah 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 dapat digunakan, misalnya, Azure Table Storage.
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 Microsoftidentity. Platform Microsoft identity adalah:
- Evolusi platform pengembang Azure Active Directory (Azure AD).
- Solusi alternatif identity untuk autentikasi dan otorisasi di aplikasi ASP.NET Core.
ASP.NET Core Identity menambahkan fungsionalitas masuk antarmuka pengguna (UI) ke aplikasi web ASP.NET Core. Untuk mengamankan API web dan SPAs, gunakan salah satu hal berikut ini:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende Identity Server
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)
- Akses menyeluruh (SSO) melalui beberapa jenis aplikasi
- Kontrol akses untuk API
- Gateway Federasi
Penting
Perangkat Lunak Duende mungkin mengharuskan Anda membayar biaya lisensi untuk penggunaan produksi Server Identity Duende. Untuk informasi lebih lanjut, lihat Bermigrasi dari ASP.NET Core 5.0 ke 6.0.
Untuk informasi selengkapnya, lihat dokumentasi Duende Identity Server (situs web Duende Software).
Lihat atau unduh kode sampel (cara mengunduh).
Membuat aplikasi Web dengan autentikasi
Buat proyek ASP.NET Core Web Application dengan Akun Pengguna Individual.
- Pilih template Aplikasi Web ASP.NET Core. Beri nama proyek WebApp1 agar memiliki namespace yang sama dengan unduhan proyek. Klik OK.
- Pada input Jenis autentikasi, pilih Akun Pengguna Individual.
Proyek yang dihasilkan menyediakan ASP.NET Core Identity sebagai Razor pustaka kelas. IdentityRazor Pustaka kelas mengekspos titik akhir dengan Identity
area . Contohnya:
- /Identity/Account/Login
- /Identity/Account/Logout
- /Identity/Account/Manage
Menerapkan migrasi
Terapkan migrasi untuk menginisialisasi database.
Jalankan perintah berikut di Package Manager Console (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 Tampilan , pilih SQL Server Object Explorer (SSOX).
- Navigasi ke (localdb)MSSQLLocalDB(SQL Server 13). Klik kanan pada dbo. Data Tampilan AspNetUsers>:
Mengonfigurasi Identity layanan
Layanan ditambahkan dalam Program.cs
. Pola umumnya adalah memanggil metode dalam urutan berikut:
Add{Service}
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 dikonfigurasi Identity dengan nilai opsi default. Layanan tersedia untuk aplikasi melalui injeksi dependensi.
Identity diaktifkan dengan memanggil UseAuthentication. UseAuthentication
menambahkan middleware autentikasi 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 Startup Aplikasi.
Scaffold Register, Login, LogOut, dan RegisterConfirmation
Register
Tambahkan file , Login
, LogOut
, dan RegisterConfirmation
. Ikuti Perancah identity ke dalam Razor proyek dengan instruksi otorisasi untuk menghasilkan kode yang ditunjukkan di bagian ini.
Periksa Daftar
Saat pengguna mengklik tombol Daftar di Register
halaman, RegisterModel.OnPostAsync
tindakan akan dipanggil. Pengguna dibuat oleh CreateAsync(TUser) pada _userManager
objek:
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 tidak diizinkan untuk diakses atau saat belum diautentikasi oleh sistem.
Ketika formulir di halaman Masuk dikirimkan, OnPostAsync
tindakan 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 Pengantar otorisasi di ASP.NET Core.
Keluar
Tautan Keluar memanggil LogoutModel.OnPost
tindakan.
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();
harus menjadi pengalihan sehingga browser melakukan permintaan baru dan identity untuk pengguna akan 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 default memungkinkan akses anonim ke home halaman. 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 masuk, keluar. Jalankan aplikasi dan pilih Privacy tautan. Anda diarahkan ke halaman masuk.
Menjelajahi Identity
Untuk menjelajahi Identity secara lebih rinci:
- Membuat sumber UI lengkap identity
- Periksa sumber setiap halaman dan telusuri debugger.
Identity Komponen
IdentitySemua paket NuGet -dependen disertakan dalam kerangka kerja 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.
TambahkanDefaultIdentity dan AddIdentity
AddDefaultIdentity diperkenalkan di ASP.NET Core 2.1. AddDefaultIdentity
Panggilan mirip dengan memanggil yang berikut ini:
Lihat Menambahkan sumberDefaultIdentity untuk informasi selengkapnya.
Mencegah penerbitan aset statis Identity
Untuk mencegah penerbitan aset statis Identity (lembar gaya dan file JavaScript untuk Identity UI) ke akar web, tambahkan properti dan RemoveIdentityAssets
target berikut ResolveStaticWebAssetsInputsDependsOn
ke file proyek aplikasi:
<PropertyGroup>
<ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>
<Target Name="RemoveIdentityAssets">
<ItemGroup>
<StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
</ItemGroup>
</Target>
Langkah berikutnya
- Lihat masalah GitHub ini untuk informasi tentang mengonfigurasi Identity menggunakan SQLite.
- Mengkonfigurasi Identity
- Membuat aplikasi ASP.NET Core dengan data pengguna yang dilindungi oleh otorisasi
- Menambahkan, mengunduh, dan menghapus data pengguna ke Identity dalam proyek ASP.NET Core
- Mengaktifkan pembuatan Kode QR untuk aplikasi pengautentikasi TOTP di ASP.NET Core
- Memigrasikan Autentikasi dan Identity ke ASP.NET Core
- Konfirmasi akun dan pemulihan kata sandi di ASP.NET Core
- Autentikasi dua faktor dengan SMS di ASP.NET Core
- Menghosting ASP.NET Core di farm web
Oleh Rick Anderson
ASP.NET Core Identity:
- 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 atau Identity mereka dapat menggunakan penyedia login eksternal. Penyedia login eksternal yang didukung termasuk Facebook, Google, Akun Microsoft, dan Twitter.
Untuk informasi tentang cara mengharuskan semua pengguna diautentikasi secara global, lihat Memerlukan pengguna yang diautentikasi.
Kode Identity sumber tersedia di GitHub. Perancah 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 dapat digunakan, misalnya, Azure Table Storage.
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 Microsoft identity adalah:
- Evolusi platform pengembang Azure Active Directory (Azure AD).
- Solusi alternatif identity untuk autentikasi dan otorisasi di aplikasi ASP.NET Core.
- Tidak terkait dengan ASP.NET Core Identity.
ASP.NET Core Identity menambahkan fungsionalitas masuk antarmuka pengguna (UI) ke aplikasi web ASP.NET Core. Untuk mengamankan API web dan SPAs, gunakan salah satu hal berikut ini:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende IdentityServer. Duende IdentityServer adalah produk pihak ke-3.
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)
- Akses menyeluruh (SSO) melalui beberapa jenis aplikasi
- Kontrol 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
Lihat atau unduh kode sampel (cara mengunduh).
Membuat aplikasi Web dengan autentikasi
Buat proyek ASP.NET Core Web Application dengan Akun Pengguna Individual.
- Pilih File>Baru>Proyek.
- Pilih ASP.NET Core Web Application. Beri nama proyek WebApp1 agar memiliki namespace yang sama dengan unduhan proyek. Klik OK.
- Pilih ASP.NET Core Web Application, lalu pilih Ubah Autentikasi.
- Pilih Akun Pengguna Individual dan klik OK.
Proyek yang dihasilkan menyediakan ASP.NET Core Identity sebagai Razor pustaka kelas. IdentityRazor Pustaka kelas mengekspos titik akhir dengan Identity
area . Contohnya:
- /Identity/Account/Login
- /Identity/Account/Logout
- /Identity/Account/Manage
Menerapkan migrasi
Terapkan migrasi untuk menginisialisasi database.
Jalankan perintah berikut di Package Manager Console (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 Tampilan , pilih SQL Server Object Explorer (SSOX).
- Navigasi ke (localdb)MSSQLLocalDB(SQL Server 13). Klik kanan pada dbo. Data Tampilan AspNetUsers>:
Mengonfigurasi Identity layanan
Layanan ditambahkan dalam 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 Identity sebelumnya dikonfigurasi dengan nilai opsi default. Layanan tersedia untuk aplikasi melalui injeksi dependensi.
Identity diaktifkan dengan memanggil UseAuthentication. UseAuthentication
menambahkan middleware autentikasi 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 dikonfigurasi Identity dengan nilai opsi default. Layanan tersedia untuk aplikasi melalui injeksi dependensi.
Identity diaktifkan dengan memanggil UseAuthentication. UseAuthentication
menambahkan middleware autentikasi 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
, , UseAuthentication
UseAuthorization
, dan UseEndpoints
harus dipanggil dalam urutan yang ditunjukkan dalam kode sebelumnya.
Untuk informasi selengkapnya tentang IdentityOptions
dan Startup
, lihat IdentityOptions dan Startup Aplikasi.
Scaffold Register, Login, LogOut, dan RegisterConfirmation
Register
Tambahkan file , Login
, LogOut
, dan RegisterConfirmation
. Ikuti Perancah identity ke dalam Razor proyek dengan instruksi otorisasi untuk menghasilkan kode yang ditunjukkan di bagian ini.
Periksa Daftar
Saat pengguna mengklik tombol Daftar di Register
halaman, RegisterModel.OnPostAsync
tindakan akan dipanggil. Pengguna dibuat oleh CreateAsync(TUser) pada _userManager
objek:
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 tidak diizinkan untuk diakses atau saat belum diautentikasi oleh sistem.
Ketika formulir di halaman Masuk dikirimkan, OnPostAsync
tindakan 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 Pengantar otorisasi di ASP.NET Core.
Keluar
Tautan Keluar memanggil LogoutModel.OnPost
tindakan.
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();
harus menjadi pengalihan sehingga browser melakukan permintaan baru dan identity untuk pengguna akan 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 default memungkinkan akses anonim ke home halaman. 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 masuk, keluar. Jalankan aplikasi dan pilih Privacy tautan. Anda diarahkan ke halaman masuk.
Menjelajahi Identity
Untuk menjelajahi Identity secara lebih rinci:
- Membuat sumber UI lengkap identity
- Periksa sumber setiap halaman dan telusuri debugger.
Identity Komponen
IdentitySemua paket NuGet -dependen disertakan dalam kerangka kerja 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 statis Identity (lembar gaya dan file JavaScript untuk Identity UI) ke akar web, tambahkan properti dan RemoveIdentityAssets
target berikut ResolveStaticWebAssetsInputsDependsOn
ke file proyek aplikasi:
<PropertyGroup>
<ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>
<Target Name="RemoveIdentityAssets">
<ItemGroup>
<StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
</ItemGroup>
</Target>
Langkah berikutnya
- kode sumber ASP.NET Core Identity
- Menambahkan sumberDefaultIdentity
- Lihat masalah GitHub ini untuk informasi tentang mengonfigurasi Identity menggunakan SQLite.
- Mengkonfigurasi Identity
- Membuat aplikasi ASP.NET Core dengan data pengguna yang dilindungi oleh otorisasi
- Menambahkan, mengunduh, dan menghapus data pengguna ke Identity dalam proyek ASP.NET Core
- Mengaktifkan pembuatan Kode QR untuk aplikasi pengautentikasi TOTP di ASP.NET Core
- Memigrasikan Autentikasi dan Identity ke ASP.NET Core
- Konfirmasi akun dan pemulihan kata sandi di ASP.NET Core
- Autentikasi dua faktor dengan SMS di ASP.NET Core
- Menghosting ASP.NET Core di farm web
ASP.NET Core