Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Oleh Steve Smith
ASP.NET Core Identity adalah sistem yang dapat diperluas yang memungkinkan Anda membuat penyedia penyimpanan kustom dan menghubungkannya ke aplikasi Anda. Topik ini menjelaskan cara membuat penyedia penyimpanan yang disesuaikan untuk ASP.NET Core Identity. Ini mencakup konsep penting untuk membuat penyedia penyimpanan Anda sendiri, tetapi bukan langkah demi langkah. Lihat Identity kustomisasi model untuk menyesuaikan Identity model.
Pendahuluan
Secara default, sistem ASP.NET Core Identity menyimpan informasi pengguna dalam database SQL Server menggunakan Entity Framework Core. Untuk banyak aplikasi, pendekatan ini berfungsi dengan baik. Namun, Anda mungkin lebih suka menggunakan mekanisme persistensi atau skema data yang berbeda. Contohnya:
- Anda menggunakan Azure Table Storage atau penyimpanan data lain.
- Tabel database Anda memiliki struktur yang berbeda.
- Anda mungkin ingin menggunakan pendekatan akses data yang berbeda, seperti Dapper.
Dalam setiap kasus ini, Anda dapat menulis penyedia yang disesuaikan untuk mekanisme penyimpanan Anda dan menyambungkan penyedia tersebut ke aplikasi Anda.
ASP.NET Core Identity disertakan dalam templat proyek di Visual Studio dengan opsi "Akun Individual".
Saat menggunakan .NET CLI, tambahkan -au Individual
:
dotnet new mvc -au Individual
Arsitektur ASP.NET Core Identity
ASP.NET Core Identity terdiri dari kelas yang disebut manajer dan toko. Manajer adalah kelas tingkat tinggi yang digunakan pengembang aplikasi untuk melakukan operasi, seperti membuat Identity pengguna. Toko adalah kelas tingkat bawah yang menentukan bagaimana entitas, seperti pengguna dan peran, dipertahankan. Toko mengikuti pola repositori dan digabungkan erat dengan mekanisme persistensi. Manajer dipisahkan dari penyimpanan, yang berarti Anda dapat mengganti mekanisme persistensi tanpa mengubah kode aplikasi Anda (kecuali untuk konfigurasi).
Diagram berikut menunjukkan bagaimana aplikasi web berinteraksi dengan manajer, saat penyimpanan berinteraksi dengan lapisan akses data.
Untuk membuat penyedia penyimpanan kustom, buat sumber data, lapisan akses data, dan kelas penyimpanan yang berinteraksi dengan lapisan akses data ini (kotak hijau dan abu-abu dalam diagram di atas). Anda tidak perlu menyesuaikan manajer atau kode aplikasi anda yang berinteraksi dengan mereka (kotak biru di atas).
Saat membuat instans UserManager
baru atau RoleManager
Anda menyediakan jenis kelas pengguna dan meneruskan instans kelas toko sebagai argumen. Pendekatan ini memungkinkan Anda untuk menyambungkan kelas yang disesuaikan ke ASP.NET Core.
Mengonfigurasi ulang aplikasi untuk menggunakan penyedia penyimpanan baru menunjukkan cara membuat instans UserManager
dan RoleManager
dengan penyimpanan yang disesuaikan.
ASP.NET Core Identity menyimpan jenis data
jenis data ASP.NET Core Identity dirinci di bagian berikut:
Pengguna
Pengguna terdaftar situs web Anda. Jenis IdentityUser dapat diperluas atau digunakan sebagai contoh untuk jenis kustom Anda sendiri. Anda tidak perlu mewarisi dari jenis tertentu untuk menerapkan solusi penyimpanan identitas kustom Anda sendiri.
Klaim Pengguna
Serangkaian pernyataan (atau Klaim) tentang pengguna yang mewakili identitas pengguna. Dapat mengaktifkan ekspresi identitas pengguna yang lebih besar daripada yang dapat dicapai melalui peran.
Login Pengguna
Informasi tentang penyedia autentikasi eksternal (seperti Facebook atau akun Microsoft) untuk digunakan saat masuk ke pengguna. Contoh
Peran
Grup otorisasi untuk situs Anda. Termasuk ID peran dan nama peran (seperti "Admin" atau "Karyawan"). Contoh
Lapisan akses data
Topik ini mengasumsikan Anda terbiasa dengan mekanisme persistensi yang akan Anda gunakan dan cara membuat entitas untuk mekanisme tersebut. Topik ini tidak memberikan detail tentang cara membuat repositori atau kelas akses data; ini memberikan beberapa saran tentang keputusan desain saat bekerja dengan ASP.NET Core Identity.
Anda memiliki banyak kebebasan saat merancang lapisan akses data untuk penyedia penyimpanan yang disesuaikan. Anda hanya perlu membuat mekanisme persistensi untuk fitur yang ingin Anda gunakan di aplikasi Anda. Misalnya, jika Anda tidak menggunakan peran di aplikasi, Anda tidak perlu membuat penyimpanan untuk peran atau asosiasi peran pengguna. Teknologi Anda dan infrastruktur yang ada mungkin memerlukan struktur yang sangat berbeda dari implementasi default ASP.NET Core Identity. Di lapisan akses data, Anda menyediakan logika untuk bekerja dengan struktur implementasi penyimpanan Anda.
Lapisan akses data menyediakan logika untuk menyimpan data dari ASP.NET Core Identity ke sumber data. Lapisan akses data untuk penyedia penyimpanan yang disesuaikan mungkin menyertakan kelas berikut untuk menyimpan informasi pengguna dan peran.
Kelas konteks
Merangkum informasi untuk menyambungkan ke mekanisme persistensi Anda dan menjalankan kueri. Beberapa kelas data memerlukan instans kelas ini, biasanya disediakan melalui injeksi dependensi. Contoh.
Penyimpanan Pengguna
Menyimpan dan mengambil informasi pengguna (seperti nama pengguna dan hash kata sandi). Contoh
Penyimpanan Peran
Menyimpan dan mengambil informasi peran (seperti nama peran). Contoh
Penyimpanan Klaim Pengguna
Menyimpan dan mengambil informasi klaim pengguna (seperti jenis dan nilai klaim). Contoh
Penyimpanan UserLogins
Menyimpan dan mengambil informasi masuk pengguna (seperti penyedia autentikasi eksternal). Contoh
Penyimpanan Peran Pengguna
Menyimpan dan mengambil peran mana yang ditetapkan ke pengguna mana. Contoh
TIPS: Hanya terapkan kelas yang ingin Anda gunakan di aplikasi Anda.
Di kelas akses data, berikan kode untuk melakukan operasi data untuk mekanisme persistensi Anda. Misalnya, dalam penyedia kustom, Anda mungkin memiliki kode berikut untuk membuat pengguna baru di kelas toko :
public async Task<IdentityResult> CreateAsync(ApplicationUser user,
CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
if (user == null) throw new ArgumentNullException(nameof(user));
return await _usersTable.CreateAsync(user);
}
Logika implementasi untuk membuat pengguna ada dalam metode , yang _usersTable.CreateAsync
ditunjukkan di bawah ini.
Mengkustomisasi kelas pengguna
Saat menerapkan penyedia penyimpanan, buat kelas pengguna yang setara dengan kelas IdentityUser.
Minimal, kelas pengguna Anda harus menyertakan Id
properti dan UserName
.
Kelas IdentityUser
menentukan properti yang dipanggil UserManager
saat melakukan operasi yang diminta. Jenis Id
default properti adalah string, tetapi Anda dapat mewarisi dari IdentityUser<TKey, TUserClaim, TUserRole, TUserLogin, TUserToken>
dan menentukan jenis yang berbeda. Kerangka kerja mengharapkan implementasi penyimpanan untuk menangani konversi jenis data.
Mengkustomisasi penyimpanan pengguna
Buat UserStore
kelas yang menyediakan metode untuk semua operasi data pada pengguna. Kelas ini setara dengan UserStore<TUser> kelas . Di kelas Anda UserStore
, terapkan IUserStore<TUser>
dan antarmuka opsional diperlukan. Anda memilih antarmuka opsional mana yang akan diterapkan berdasarkan fungsionalitas yang disediakan di aplikasi Anda.
Antarmuka opsional
- IUserRoleStore
- IUserClaimStore
- IUserPasswordStore
- IUserSecurityStampStore
- IUserEmailStore
- IUserPhoneNumberStore
- IQueryableUserStore
- IUserLoginStore
- IUserTwoFactorStore
- IUserLockoutStore
Antarmuka opsional mewarisi dari IUserStore<TUser>
. Anda dapat melihat penyimpanan pengguna sampel yang diimplementasikan sebagian di aplikasi sampel.
UserStore
Dalam kelas , Anda menggunakan kelas akses data yang Anda buat untuk melakukan operasi. Ini diteruskan menggunakan injeksi dependensi. Misalnya, di SQL Server dengan implementasi Dapper, UserStore
kelas memiliki CreateAsync
metode yang menggunakan instans DapperUsersTable
untuk menyisipkan rekaman baru:
public async Task<IdentityResult> CreateAsync(ApplicationUser user)
{
string sql = "INSERT INTO dbo.CustomUser " +
"VALUES (@id, @Email, @EmailConfirmed, @PasswordHash, @UserName)";
int rows = await _connection.ExecuteAsync(sql, new { user.Id, user.Email, user.EmailConfirmed, user.PasswordHash, user.UserName });
if(rows > 0)
{
return IdentityResult.Success;
}
return IdentityResult.Failed(new IdentityError { Description = $"Could not insert user {user.Email}." });
}
Antarmuka yang akan diterapkan saat menyesuaikan penyimpanan pengguna
-
IUserStore
Antarmuka IUserStore<TUser> adalah satu-satunya antarmuka yang harus Anda terapkan di penyimpanan pengguna. Ini mendefinisikan metode untuk membuat, memperbarui, menghapus, dan mengambil pengguna. -
IUserClaimStore
Antarmuka IUserClaimStore<TUser> menentukan metode yang Anda terapkan untuk mengaktifkan klaim pengguna. Ini berisi metode untuk menambahkan, menghapus, dan mengambil klaim pengguna. -
IUserLoginStore
IUserLoginStore<TUser> menentukan metode yang Anda terapkan untuk mengaktifkan penyedia autentikasi eksternal. Ini berisi metode untuk menambahkan, menghapus, dan mengambil login pengguna, dan metode untuk mengambil pengguna berdasarkan informasi masuk. -
IUserRoleStore
Antarmuka IUserRoleStore<TUser> menentukan metode yang Anda terapkan untuk memetakan pengguna ke peran. Ini berisi metode untuk menambahkan, menghapus, dan mengambil peran pengguna, dan metode untuk memeriksa apakah pengguna ditetapkan ke peran. -
IUserPasswordStore
Antarmuka IUserPasswordStore<TUser> menentukan metode yang Anda terapkan untuk mempertahankan kata sandi yang di-hash. Ini berisi metode untuk mendapatkan dan mengatur kata sandi yang di-hash, dan metode yang menunjukkan apakah pengguna telah mengatur kata sandi. -
IUserSecurityStampStore
Antarmuka IUserSecurityStampStore<TUser> menentukan metode yang Anda terapkan untuk menggunakan stempel keamanan untuk menunjukkan apakah informasi akun pengguna telah berubah. Stempel ini diperbarui ketika pengguna mengubah kata sandi, atau menambahkan atau menghapus login. Ini berisi metode untuk mendapatkan dan mengatur stempel keamanan. -
IUserTwoFactorStore
Antarmuka IUserTwoFactorStore<TUser> menentukan metode yang Anda terapkan untuk mendukung autentikasi dua faktor. Ini berisi metode untuk mendapatkan dan mengatur apakah autentikasi dua faktor diaktifkan untuk pengguna. -
IUserPhoneNumberStore
Antarmuka IUserPhoneNumberStore<TUser> menentukan metode yang Anda terapkan untuk menyimpan nomor telepon pengguna. Ini berisi metode untuk mendapatkan dan mengatur nomor telepon dan apakah nomor telepon dikonfirmasi. -
IUserEmailStore
Antarmuka IUserEmailStore<TUser> menentukan metode yang Anda terapkan untuk menyimpan alamat email pengguna. Ini berisi metode untuk mendapatkan dan mengatur alamat email dan apakah email dikonfirmasi. -
IUserLockoutStore
Antarmuka IUserLockoutStore<TUser> menentukan metode yang Anda terapkan untuk menyimpan informasi tentang mengunci akun. Ini berisi metode untuk melacak upaya akses dan penguncian yang gagal. -
IQueryableUserStore
Antarmuka IQueryableUserStore<TUser> menentukan anggota yang Anda terapkan untuk menyediakan penyimpanan pengguna yang dapat dikueri.
Anda hanya mengimplementasikan antarmuka yang diperlukan di aplikasi Anda. Contohnya:
public class UserStore : IUserStore<IdentityUser>,
IUserClaimStore<IdentityUser>,
IUserLoginStore<IdentityUser>,
IUserRoleStore<IdentityUser>,
IUserPasswordStore<IdentityUser>,
IUserSecurityStampStore<IdentityUser>
{
// interface implementations not shown
}
IdentityUserClaim, IdentityUserLogin, dan IdentityUserRole
Namespace Microsoft.AspNet.Identity.EntityFramework
berisi implementasi kelas IdentityUserClaim, IdentityUserLogin, dan IdentityUserRole . Jika Anda menggunakan fitur-fitur ini, Anda mungkin ingin membuat versi kelas ini sendiri dan menentukan properti untuk aplikasi Anda. Namun, terkadang lebih efisien untuk tidak memuat entitas ini ke dalam memori saat melakukan operasi dasar (seperti menambahkan atau menghapus klaim pengguna). Sebagai gantinya, kelas penyimpanan backend dapat menjalankan operasi ini langsung pada sumber data. Misalnya, UserStore.GetClaimsAsync
metode dapat memanggil userClaimTable.FindByUserId(user.Id)
metode untuk menjalankan kueri pada tabel tersebut secara langsung dan mengembalikan daftar klaim.
Mengkustomisasi kelas peran
Saat menerapkan penyedia penyimpanan peran, Anda dapat membuat jenis peran kustom. Ini tidak perlu menerapkan antarmuka tertentu, tetapi harus memiliki Id
dan biasanya akan memiliki Name
properti.
Berikut ini adalah contoh kelas peran:
using System;
namespace CustomIdentityProviderSample.CustomProvider
{
public class ApplicationRole
{
public Guid Id { get; set; } = Guid.NewGuid();
public string Name { get; set; }
}
}
Mengkustomisasi penyimpanan peran
Anda dapat membuat RoleStore
kelas yang menyediakan metode untuk semua operasi data pada peran. Kelas ini setara dengan kelas RoleStore<TRole> .
RoleStore
Di kelas , Anda mengimplementasikan IRoleStore<TRole>
dan secara IQueryableRoleStore<TRole>
opsional antarmuka .
-
IRoleStore<TRole>
Antarmuka IRoleStore<TRole> mendefinisikan metode yang akan diterapkan di kelas penyimpanan peran. Ini berisi metode untuk membuat, memperbarui, menghapus, dan mengambil peran. -
RoleStore<TRole>
Untuk menyesuaikanRoleStore
, buat kelas yang mengimplementasikanIRoleStore<TRole>
antarmuka.
Mengonfigurasi ulang aplikasi untuk menggunakan penyedia penyimpanan baru
Setelah menerapkan penyedia penyimpanan, Anda mengonfigurasi aplikasi untuk menggunakannya. Jika aplikasi Anda menggunakan penyedia default, ganti dengan penyedia kustom Anda.
-
Microsoft.AspNetCore.EntityFramework.Identity
Hapus paket NuGet. - Jika penyedia penyimpanan berada dalam proyek atau paket terpisah, tambahkan referensi ke dalamnya.
- Ganti semua referensi ke
Microsoft.AspNetCore.EntityFramework.Identity
dengan pernyataan penggunaan untuk namespace penyedia penyimpanan Anda. -
AddIdentity
Ubah metode untuk menggunakan jenis kustom. Anda dapat membuat metode ekstensi Anda sendiri untuk tujuan ini. Lihat IdentityServiceCollectionExtensions misalnya. - Jika Anda menggunakan Peran, perbarui
RoleManager
untuk menggunakan kelas AndaRoleStore
. - Perbarui string koneksi dan kredensial ke konfigurasi aplikasi Anda.
Peringatan
Artikel ini memperlihatkan penggunaan string koneksi. Dengan database lokal, pengguna tidak perlu diautentikasi, tetapi dalam produksi, string koneksi terkadang menyertakan kata sandi untuk mengautentikasi. Kredensial kata sandi pemilik sumber daya (ROPC) adalah risiko keamanan yang harus dihindari dalam database produksi. Aplikasi produksi harus menggunakan alur autentikasi paling aman yang tersedia. Untuk informasi selengkapnya tentang autentikasi untuk aplikasi yang disebarkan untuk menguji atau lingkungan produksi, lihat Mengamankan alur autentikasi.
Contoh:
public void ConfigureServices(IServiceCollection services)
{
// Add identity types
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddDefaultTokenProviders();
// Identity Services
services.AddTransient<IUserStore<ApplicationUser>, CustomUserStore>();
services.AddTransient<IRoleStore<ApplicationRole>, CustomRoleStore>();
string connectionString = Configuration.GetConnectionString("DefaultConnection");
services.AddTransient<SqlConnection>(e => new SqlConnection(connectionString));
services.AddTransient<DapperUsersTable>();
// additional configuration
}
var builder = WebApplication.CreateBuilder(args);
// Add identity types
builder.Services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddDefaultTokenProviders();
// Identity Services
builder.Services.AddTransient<IUserStore<ApplicationUser>, CustomUserStore>();
builder.Services.AddTransient<IRoleStore<ApplicationRole>, CustomRoleStore>();
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddTransient<SqlConnection>(e => new SqlConnection(connectionString));
builder.Services.AddTransient<DapperUsersTable>();
// additional configuration
builder.Services.AddRazorPages();
var app = builder.Build();
Referensi
- Identity kustomisasi model
- Penyedia Penyimpanan Kustom untuk ASP.NET 4.x Identity
- ASP.NET Core Identity: Repositori ini mencakup tautan ke penyedia toko yang dikelola komunitas.
- Lihat atau unduh sampel dari GitHub.
ASP.NET Core