Cara menggunakan Identity untuk mengamankan backend API Web untuk SPAs
Catatan
Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Penting
Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.
Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
ASP.NET Core Identity menyediakan API yang menangani autentikasi, otorisasi, dan manajemen identitas. API memungkinkan untuk mengamankan titik akhir backend API Web dengan cookieautentikasi berbasis. Ada opsi berbasis token untuk klien yang tidak dapat menggunakannya cookie.
Artikel ini menunjukkan cara menggunakan Identity untuk mengamankan backend API Web untuk SPAs seperti aplikasi Angular, React, dan Vue. API backend yang sama dapat digunakan untuk mengamankan Blazor WebAssembly aplikasi.
Prasyarat
Langkah-langkah yang ditunjukkan dalam artikel ini menambahkan autentikasi dan otorisasi ke aplikasi ASP.NET Core Web API yang:
- Belum dikonfigurasi untuk autentikasi.
- Target atau yang lebih
net8.0
baru. - Dapat berupa API minimal atau API berbasis pengontrol.
Beberapa instruksi pengujian dalam artikel ini menggunakan antarmuka pengguna Swagger yang disertakan dengan templat proyek. Antarmuka pengguna Swagger tidak diperlukan untuk digunakan Identity dengan backend API Web.
Instal paket NuGet
Instal paket NuGet berikut:
Microsoft.AspNetCore.Identity.EntityFrameworkCore
- Memungkinkan Identity untuk bekerja dengan Entity Framework Core (EF Core).- Salah satu yang memungkinkan EF Core untuk bekerja dengan database, seperti salah satu paket berikut:
Untuk cara tercepat untuk memulai, gunakan database dalam memori.
Ubah database nanti ke SQLite atau SQL Server untuk menyimpan data pengguna antar sesi saat menguji atau untuk penggunaan produksi. Itu memperkenalkan beberapa kompleksitas dibandingkan dengan dalam memori, karena mengharuskan database dibuat melalui migrasi, seperti yang EF Core ditunjukkan dalam tutorial memulai.
Instal paket ini dengan menggunakan manajer paket NuGet di Visual Studio atau perintah CLI tambahkan paket dotnet.
Buat IdentityDbContext
Tambahkan kelas bernama ApplicationDbContext
yang mewarisi dari IdentityDbContext<TUser>:
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
public class ApplicationDbContext : IdentityDbContext<IdentityUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) :
base(options)
{ }
}
Kode yang ditampilkan menyediakan konstruktor khusus yang memungkinkan untuk mengonfigurasi database untuk lingkungan yang berbeda.
Tambahkan satu atau beberapa arahan berikut sesuai using
kebutuhan saat menambahkan kode yang diperlihatkan dalam langkah-langkah ini.
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
EF Core Mengonfigurasi konteks
Seperti disebutkan sebelumnya, cara paling sederhana untuk memulai adalah dengan menggunakan database dalam memori. Dengan setiap eksekusi dalam memori dimulai dengan database baru, dan tidak perlu menggunakan migrasi. Setelah panggilan ke WebApplication.CreateBuilder(args)
, tambahkan kode berikut untuk dikonfigurasi Identity untuk menggunakan database dalam memori:
builder.Services.AddDbContext<ApplicationDbContext>(
options => options.UseInMemoryDatabase("AppDb"));
Untuk menyimpan data pengguna antar sesi saat menguji atau untuk penggunaan produksi, ubah database nanti ke SQLite atau SQL Server.
Menambahkan Identity layanan ke kontainer
Setelah panggilan ke WebApplication.CreateBuilder(args)
, panggil AddAuthorization untuk menambahkan layanan ke kontainer injeksi dependensi (DI):
builder.Services.AddAuthorization();
Mengaktifkan Identity API
Setelah panggilan ke WebApplication.CreateBuilder(args)
, panggil AddIdentityApiEndpoints<TUser>(IServiceCollection) dan AddEntityFrameworkStores<TContext>(IdentityBuilder).
builder.Services.AddIdentityApiEndpoints<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
Secara default, token cookies dan kepemilikan diaktifkan. Cookies dan token dikeluarkan saat masuk jika useCookies
parameter string kueri di titik akhir login adalah true
.
Rute peta Identity
Setelah panggilan ke builder.Build()
, panggil MapIdentityApi<TUser>(IEndpointRouteBuilder) untuk memetakan Identity titik akhir:
app.MapIdentityApi<IdentityUser>();
Mengamankan titik akhir yang dipilih
Untuk mengamankan titik akhir, gunakan RequireAuthorization metode ekstensi pada Map{Method}
panggilan yang menentukan rute. Contohnya:
app.MapGet("/weatherforecast", (HttpContext httpContext) =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = summaries[Random.Shared.Next(summaries.Length)]
})
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi()
.RequireAuthorization();
Metode ini RequireAuthorization
juga dapat digunakan untuk:
Titik akhir UI Swagger Aman, seperti yang ditunjukkan dalam contoh berikut:
app.MapSwagger().RequireAuthorization();
Amankan dengan klaim atau izin tertentu, seperti yang ditunjukkan dalam contoh berikut:
.RequireAuthorization("Admin");
Dalam proyek API web berbasis pengontrol, titik akhir aman dengan menerapkan atribut [Authorize
] ke pengontrol atau tindakan.
Menguji API
Cara cepat untuk menguji autentikasi adalah dengan menggunakan database dalam memori dan antarmuka pengguna Swagger yang disertakan dengan templat proyek. Langkah-langkah berikut menunjukkan cara menguji API dengan antarmuka pengguna Swagger. Pastikan bahwa titik akhir antarmuka pengguna Swagger tidak diamankan.
Mencoba mengakses titik akhir aman
- Jalankan aplikasi dan navigasikan ke antarmuka pengguna Swagger.
- Perluas titik akhir aman, seperti
/weatherforecast
dalam proyek yang dibuat oleh templat API web. - Pilih Coba.
- Pilih Jalankan. Responsnya adalah
401 - not authorized
.
Uji pendaftaran
Perluas
/register
dan pilih Cobalah.Di bagian Parameter UI, isi permintaan sampel ditampilkan:
{ "email": "string", "password": "string" }
Ganti "string" dengan alamat email dan kata sandi yang valid, lalu pilih Jalankan.
Untuk mematuhi aturan validasi kata sandi default, panjang kata sandi harus setidaknya enam karakter dan berisi setidaknya satu dari masing-masing karakter berikut:
- Huruf besar
- Huruf kecil
- Digit numerik
- Karakter non-nufanumerik
Jika Anda memasukkan alamat email yang tidak valid atau kata sandi yang buruk, hasilnya menyertakan kesalahan validasi. Berikut adalah contoh isi respons dengan kesalahan validasi:
{ "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", "title": "One or more validation errors occurred.", "status": 400, "errors": { "PasswordTooShort": [ "Passwords must be at least 6 characters." ], "PasswordRequiresNonAlphanumeric": [ "Passwords must have at least one non alphanumeric character." ], "PasswordRequiresDigit": [ "Passwords must have at least one digit ('0'-'9')." ], "PasswordRequiresLower": [ "Passwords must have at least one lowercase ('a'-'z')." ] } }
Kesalahan dikembalikan dalam format ProblemDetails sehingga klien dapat mengurainya dan menampilkan kesalahan validasi sesuai kebutuhan.
Pendaftaran yang berhasil menghasilkan
200 - OK
respons.
Uji login
Perluas
/login
dan pilih Cobalah. Contoh isi permintaan menunjukkan dua parameter tambahan:{ "email": "string", "password": "string", "twoFactorCode": "string", "twoFactorRecoveryCode": "string" }
Properti ON tambahan JStidak diperlukan untuk contoh ini dan dapat dihapus. Atur
useCookies
ketrue
.Ganti "string" dengan alamat email dan kata sandi yang Anda gunakan untuk mendaftar, lalu pilih Jalankan.
Login yang berhasil menghasilkan
200 - OK
respons dengan cookie di header respons.
Coba lagi titik akhir aman
Setelah berhasil masuk, jalankan ulang titik akhir aman. Autentikasi cookie dikirim secara otomatis dengan permintaan, dan titik akhir diotorisasi. CookieAutentikasi berbasis aman bawaan ke browser dan "hanya berfungsi."
Pengujian dengan klien nonbrowser
Beberapa klien web mungkin tidak menyertakan cookies di header secara default:
Jika Anda menggunakan alat untuk menguji API, Anda mungkin perlu mengaktifkannya cookiedi pengaturan.
API JavaScript
fetch
tidak menyertakan cookiesecara default. Aktifkan dengan mengaturcredentials
ke nilaiinclude
dalam opsi.Yang
HttpClient
berjalan di Blazor WebAssembly aplikasi memerlukanHttpRequestMessage
untuk menyertakan kredensial, seperti contoh berikut:request.SetBrowserRequestCredential(BrowserRequestCredentials.Include);
Menggunakan autentikasi berbasis token
Untuk klien yang tidak mendukung cookie, API login menyediakan parameter untuk meminta token. Token kustom (yang merupakan milik platform identitas ASP.NET Core) dikeluarkan yang dapat digunakan untuk mengautentikasi permintaan berikutnya. Token diteruskan di Authorization
header sebagai token pembawa. Token refresh juga disediakan. Token ini memungkinkan aplikasi untuk meminta token baru ketika yang lama kedaluwarsa tanpa memaksa pengguna untuk masuk lagi.
Token bukan on Web Token standar JS(JWT). Penggunaan token kustom disengaja, karena API bawaan Identity dimaksudkan terutama untuk skenario sederhana. Opsi token tidak dimaksudkan untuk menjadi penyedia layanan identitas berfitur lengkap atau server token, tetapi sebagai alternatif untuk cookie opsi untuk klien yang tidak dapat menggunakannya cookie.
Untuk menggunakan autentikasi berbasis token, atur useCookies
parameter string kueri ke false
saat memanggil /login
titik akhir. Token menggunakan skema autentikasi pembawa . Menggunakan token yang dikembalikan dari panggilan ke /login
, panggilan berikutnya ke titik akhir yang dilindungi harus menambahkan header Authorization: Bearer <token>
di mana <token>
adalah token akses. Untuk informasi selengkapnya, lihat Menggunakan POST /login
titik akhir nanti di artikel ini.
Keluar
Untuk menyediakan cara bagi pengguna untuk keluar, tentukan /logout
titik akhir seperti contoh berikut:
app.MapPost("/logout", async (SignInManager<IdentityUser> signInManager,
[FromBody] object empty) =>
{
if (empty != null)
{
await signInManager.SignOutAsync();
return Results.Ok();
}
return Results.Unauthorized();
})
.WithOpenApi()
.RequireAuthorization();
Berikan objek ON kosong JS({}
) di isi permintaan saat memanggil titik akhir ini. Kode berikut adalah contoh panggilan ke titik akhir keluar:
public signOut() {
return this.http.post('/logout', {}, {
withCredentials: true,
observe: 'response',
responseType: 'text'
Titik MapIdentityApi<TUser>
akhir
Panggilan untuk MapIdentityApi<TUser>
menambahkan titik akhir berikut ke aplikasi:
POST /register
POST /login
POST /refresh
GET /confirmEmail
POST /resendConfirmationEmail
POST /forgotPassword
POST /resetPassword
POST /manage/2fa
GET /manage/info
POST /manage/info
POST /register
Menggunakan titik akhir
Isi permintaan harus memiliki Email properti dan Password :
{
"email": "string",
"password": "string",
}
Untuk informasi selengkapnya, lihat:
- Uji pendaftaran sebelumnya dalam artikel ini.
- RegisterRequest.
POST /login
Menggunakan titik akhir
Dalam isi permintaan, Email dan Password diperlukan. Jika autentikasi dua faktor (2FA) diaktifkan, baik TwoFactorCode atau TwoFactorRecoveryCode diperlukan. Jika 2FA tidak diaktifkan, hilangkan keduanya twoFactorCode
dan twoFactorRecoveryCode
. Untuk informasi selengkapnya, lihat Menggunakan POST /manage/2fa
titik akhir nanti di artikel ini.
Berikut adalah contoh isi permintaan dengan 2FA tidak diaktifkan:
{
"email": "string",
"password": "string"
}
Berikut adalah contoh isi permintaan dengan 2FA diaktifkan:
-
{ "email": "string", "password": "string", "twoFactorCode": "string", }
-
{ "email": "string", "password": "string", "twoFactorRecoveryCode": "string" }
Titik akhir mengharapkan parameter string kueri:
useCookies
- Atur ketrue
untuk cookieautentikasi berbasis. Atur kefalse
atau hilangkan untuk autentikasi berbasis token.
Untuk informasi selengkapnya tentang cookieautentikasi berbasis, lihat Menguji login sebelumnya di artikel ini.
Autentikasi berbasis token
Jika useCookies
atau dihilangkan false
, autentikasi berbasis token diaktifkan. Isi respons mencakup properti berikut:
{
"tokenType": "string",
"accessToken": "string",
"expiresIn": 0,
"refreshToken": "string"
}
Untuk informasi selengkapnya tentang properti ini, lihat AccessTokenResponse.
Letakkan token akses di header untuk membuat permintaan terautentikasi, seperti yang ditunjukkan dalam contoh berikut
Authorization: Bearer {access token}
Saat token akses akan kedaluwarsa, panggil titik akhir /refresh .
POST /refresh
Menggunakan titik akhir
Untuk digunakan hanya dengan autentikasi berbasis token. Mendapatkan token akses baru tanpa memaksa pengguna untuk masuk lagi. Panggil titik akhir ini saat token akses akan kedaluwarsa.
Isi permintaan hanya RefreshTokenberisi . Berikut adalah contoh isi permintaan:
{
"refreshToken": "string"
}
Jika panggilan berhasil, isi respons adalah baru AccessTokenResponse, seperti yang ditunjukkan dalam contoh berikut:
{
"tokenType": "string",
"accessToken": "string",
"expiresIn": 0,
"refreshToken": "string"
}
GET /confirmEmail
Menggunakan titik akhir
Jika Identity disiapkan untuk konfirmasi email, panggilan yang berhasil ke /register
titik akhir akan mengirim email yang berisi tautan ke /confirmEmail
titik akhir. Tautan berisi parameter string kueri berikut:
userId
code
changedEmail
- Disertakan hanya jika pengguna mengubah alamat email selama pendaftaran.
Identity menyediakan teks default untuk email konfirmasi. Secara default, subjek email adalah "Konfirmasi email Anda" dan isi email terlihat seperti contoh berikut:
Please confirm your account by <a href='https://contoso.com/confirmEmail?userId={user ID}&code={generated code}&changedEmail={new email address}'>clicking here</a>.
RequireConfirmedEmail Jika properti diatur ke true
, pengguna tidak dapat masuk hingga alamat email dikonfirmasi dengan mengklik tautan dalam email. Titik /confirmEmail
akhir:
- Mengonfirmasi alamat email dan memungkinkan pengguna untuk masuk.
- Mengembalikan teks "Terima kasih telah mengonfirmasi email Anda." di isi respons.
Untuk menyiapkan Identity konfirmasi email, tambahkan kode untuk Program.cs
diatur RequireConfirmedEmail
ke true
dan tambahkan kelas yang diterapkan IEmailSender ke kontainer DI. Contohnya:
builder.Services.Configure<IdentityOptions>(options =>
{
options.SignIn.RequireConfirmedEmail = true;
});
builder.Services.AddTransient<IEmailSender, EmailSender>();
Untuk informasi selengkapnya, lihat Konfirmasi akun dan pemulihan kata sandi di ASP.NET Core.
Identity menyediakan teks default untuk email lain yang perlu dikirim juga, seperti untuk 2FA dan pengaturan ulang kata sandi. Untuk menyesuaikan email ini, berikan implementasi IEmailSender
kustom antarmuka. Dalam contoh sebelumnya, EmailSender
adalah kelas yang mengimplementasikan IEmailSender
. Untuk informasi selengkapnya, termasuk contoh kelas yang menerapkan IEmailSender
, lihat Konfirmasi akun dan pemulihan kata sandi di ASP.NET Core.
POST /resendConfirmationEmail
Menggunakan titik akhir
Mengirim email hanya jika alamat tersebut valid untuk pengguna terdaftar.
Isi permintaan hanya Emailberisi . Berikut adalah contoh isi permintaan:
{
"email": "string"
}
Untuk informasi selengkapnya, lihat Menggunakan GET /confirmEmail
titik akhir sebelumnya di artikel ini.
POST /forgotPassword
Menggunakan titik akhir
Menghasilkan email yang berisi kode reset kata sandi. Kirim kode tersebut ke /resetPassword
dengan kata sandi baru.
Isi permintaan hanya Emailberisi . Berikut contohnya:
{
"email": "string"
}
Untuk informasi tentang cara mengaktifkan Identity untuk mengirim email, lihat Menggunakan GET /confirmEmail
titik akhir.
POST /resetPassword
Menggunakan titik akhir
Panggil titik akhir ini setelah mendapatkan kode reset dengan memanggil /forgotPassword
titik akhir.
Isi permintaan memerlukan Email, , ResetCodedan NewPassword. Berikut contohnya:
{
"email": "string",
"resetCode": "string",
"newPassword": "string"
}
POST /manage/2fa
Menggunakan titik akhir
Mengonfigurasi autentikasi dua faktor (2FA) untuk pengguna. Ketika 2FA diaktifkan, login yang berhasil memerlukan kode yang dihasilkan oleh aplikasi pengautentikasi selain alamat email dan kata sandi.
Aktifkan 2FA
Untuk mengaktifkan 2FA untuk pengguna yang saat ini diautentikasi:
/manage/2fa
Panggil titik akhir, kirim objek ON kosong JS({}
) di isi permintaan.Isi respons menyediakan SharedKey bersama dengan beberapa properti lain yang tidak diperlukan pada saat ini. Kunci bersama digunakan untuk menyiapkan aplikasi pengautentikasi. Contoh badan respons:
{ "sharedKey": "string", "recoveryCodesLeft": 0, "recoveryCodes": null, "isTwoFactorEnabled": false, "isMachineRemembered": false }
Gunakan kunci bersama untuk mendapatkan kata sandi satu kali berbasis waktu (TOTP). Untuk informasi selengkapnya, lihat Mengaktifkan pembuatan kode QR untuk aplikasi pengautentikasi TOTP di ASP.NET Core.
/manage/2fa
Panggil titik akhir, kirim TOTP dan"enable": true
di isi permintaan. Contohnya:{ "enable": true, "twoFactorCode": "string" }
Isi respons mengonfirmasi bahwa IsTwoFactorEnabled itu benar dan menyediakan RecoveryCodes. Kode pemulihan digunakan untuk masuk saat aplikasi pengautentikasi tidak tersedia. Contoh isi respons setelah berhasil mengaktifkan 2FA:
{ "sharedKey": "string", "recoveryCodesLeft": 10, "recoveryCodes": [ "string", "string", "string", "string", "string", "string", "string", "string", "string", "string" ], "isTwoFactorEnabled": true, "isMachineRemembered": false }
Masuk dengan 2FA
/login
Panggil titik akhir, kirim alamat email, kata sandi, dan TOTP di isi permintaan. Contohnya:
{
"email": "string",
"password": "string",
"twoFactorCode": "string"
}
Jika pengguna tidak memiliki akses ke aplikasi pengautentikasi, masuk dengan memanggil /login
titik akhir dengan salah satu kode pemulihan yang disediakan saat 2FA diaktifkan. Isi permintaan terlihat seperti contoh berikut:
{
"email": "string",
"password": "string",
"twoFactorRecoveryCode": "string"
}
Mengatur ulang kode pemulihan
Untuk mendapatkan kumpulan kode pemulihan baru, panggil titik akhir ini dengan ResetRecoveryCodes diatur ke true
. Berikut adalah contoh isi permintaan:
{
"resetRecoveryCodes": true
}
Mereset kunci bersama
Untuk mendapatkan kunci bersama acak baru, panggil titik akhir ini dengan ResetSharedKey diatur ke true
. Berikut adalah contoh isi permintaan:
{
"resetSharedKey": true
}
Mengatur ulang kunci secara otomatis menonaktifkan persyaratan masuk dua faktor untuk pengguna yang diautentikasi hingga diaktifkan kembali oleh permintaan selanjutnya.
Lupakan mesin
Untuk menghapus cookie "ingat bendera saya" jika ada, panggil titik akhir ini dengan ForgetMachine diatur ke true. Berikut adalah contoh isi permintaan:
{
"forgetMachine": true
}
Titik akhir ini tidak berdampak pada autentikasi berbasis token.
GET /manage/info
Menggunakan titik akhir
Mendapatkan alamat email dan status konfirmasi email pengguna yang masuk. Klaim dihilangkan dari titik akhir ini karena alasan keamanan. Jika klaim diperlukan, gunakan API sisi server untuk menyiapkan titik akhir untuk klaim. Atau alih-alih membagikan semua klaim pengguna, berikan titik akhir validasi yang menerima klaim dan merespons apakah pengguna memilikinya.
Permintaan tidak memerlukan parameter apa pun. Isi respons mencakup Email properti dan IsEmailConfirmed , seperti dalam contoh berikut:
{
"email": "string",
"isEmailConfirmed": true
}
POST /manage/info
Menggunakan titik akhir
Memperbarui alamat email dan kata sandi pengguna yang masuk. Kirim NewEmail, NewPassword, dan OldPassword dalam isi permintaan, seperti yang ditunjukkan dalam contoh berikut:
{
"newEmail": "string",
"newPassword": "string",
"oldPassword": "string"
}
Berikut contoh isi responsnya:
{
"email": "string",
"isEmailConfirmed": false
}
Lihat juga
Untuk informasi selengkapnya, lihat sumber daya berikut:
- Memilih solusi manajemen identitas
- Identity solusi manajemen untuk aplikasi web .NET
- Otorisasi sederhana di ASP.NET Core
- Menambahkan, mengunduh, dan menghapus data pengguna ke Identity dalam proyek ASP.NET Core
- Membuat aplikasi ASP.NET Core dengan data pengguna yang dilindungi oleh otorisasi
- Konfirmasi akun dan pemulihan kata sandi di ASP.NET Core
- Mengaktifkan pembuatan Kode QR untuk aplikasi pengautentikasi TOTP di ASP.NET Core
- Contoh backend API Web untuk SPAs File .http menunjukkan autentikasi berbasis token. Misalnya:
- Tidak diatur
useCookies
- Menggunakan header Otorisasi untuk meneruskan token
- Menampilkan refresh untuk memperpanjang sesi tanpa memaksa pengguna untuk masuk lagi
- Tidak diatur
- Sampel aplikasi Angular yang menggunakan Identity untuk mengamankan backend API Web
Templat ASP.NET Core menawarkan autentikasi di Aplikasi Halaman Tunggal (SPAs) menggunakan dukungan untuk otorisasi API. ASP.NET Core Identity untuk mengautentikasi dan menyimpan pengguna dikombinasikan dengan Duende Identity Server untuk menerapkan Koneksi OpenID.
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.
Parameter autentikasi ditambahkan ke templat proyek Angular dan React yang mirip dengan parameter autentikasi di templat proyek Aplikasi Web (Model-View-Controller) (MVC) dan Aplikasi Web (Razor Halaman). Nilai parameter yang diizinkan adalah Tidak Ada dan Individual. Templat proyek React.js dan Redux saat ini tidak mendukung parameter autentikasi.
Membuat aplikasi dengan dukungan otorisasi API
Autentikasi dan otorisasi pengguna dapat digunakan dengan Angular dan React SPAs. Buka shell perintah, dan jalankan perintah berikut:
Sudut:
dotnet new angular -au Individual
React:
dotnet new react -au Individual
Perintah sebelumnya membuat aplikasi ASP.NET Core dengan direktori ClientApp yang berisi SPA.
Deskripsi umum komponen ASP.NET Core aplikasi
Bagian berikut menjelaskan penambahan ke proyek saat dukungan autentikasi disertakan:
Program.cs
Contoh kode berikut mengandalkan Microsoft.AspNetCore.ApiAuthorization.IdentityPaket NuGet Server . Contoh mengonfigurasi autentikasi dan otorisasi API menggunakan AddApiAuthorization metode ekstensi dan AddIdentityServerJwt . Proyek yang menggunakan templat proyek React atau Angular SPA dengan autentikasi menyertakan referensi ke paket ini.
dotnet new angular -au Individual
menghasilkan file berikut Program.cs
:
using Microsoft.AspNetCore.Authentication;
using Microsoft.EntityFrameworkCore;
using output_directory_name.Data;
using output_directory_name.Models;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
builder.Services.AddAuthentication()
.AddIdentityServerJwt();
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseIdentityServer();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
app.MapRazorPages();
app.MapFallbackToFile("index.html");
app.Run();
Kode sebelumnya mengonfigurasi:
Identity dengan UI default:
builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlite(connectionString)); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<ApplicationDbContext>();
IdentityServer dengan metode pembantu Identitytambahan
AddApiAuthorization
yang menyiapkan beberapa konvensi ASP.NET Core default di atas Server:builder.Services.AddIdentityServer() .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
Autentikasi dengan metode pembantu tambahan
AddIdentityServerJwt
yang mengonfigurasi aplikasi untuk memvalidasi token JWT yang diproduksi oleh IdentityServer:builder.Services.AddAuthentication() .AddIdentityServerJwt();
Middleware autentikasi yang bertanggung jawab untuk memvalidasi kredensial permintaan dan mengatur pengguna pada konteks permintaan:
app.UseAuthentication();
IdentityMiddleware Server yang mengekspos titik akhir Koneksi OpenID:
app.UseIdentityServer();
Azure App Service di Linux
Untuk penyebaran Azure App Service di Linux, tentukan penerbit secara eksplisit:
builder.Services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
options.Authority = "{AUTHORITY}";
});
Dalam kode sebelumnya, {AUTHORITY}
tempat penampung adalah Authority untuk digunakan saat melakukan panggilan Koneksi OpenID.
Contoh:
options.Authority = "https://contoso-service.azurewebsites.net";
AddApiAuthorization
Metode pembantu Identityini mengonfigurasi Server untuk menggunakan konfigurasi kami yang didukung. IdentityServer adalah kerangka kerja yang kuat dan dapat diperluas untuk menangani masalah keamanan aplikasi. Pada saat yang sama, yang mengekspos kompleksitas yang tidak perlu untuk skenario yang paling umum. Akibatnya, serangkaian konvensi dan opsi konfigurasi disediakan untuk Anda yang dianggap sebagai titik awal yang baik. Setelah autentikasi Anda perlu berubah, kekuatan Identitypenuh Server masih tersedia untuk menyesuaikan autentikasi agar sesuai dengan kebutuhan Anda.
AddIdentityServerJwt
Metode pembantu ini mengonfigurasi skema kebijakan untuk aplikasi sebagai penangan autentikasi default. Kebijakan dikonfigurasi untuk memungkinkan Identity menangani semua permintaan yang dirutekan ke subpath apa pun di Identity ruang URL "/Identity". Menangani JwtBearerHandler
semua permintaan lainnya. Selain itu, metode ini mendaftarkan <<ApplicationName>>API
sumber daya API dengan IdentityServer dengan cakupan <<ApplicationName>>API
default dan mengonfigurasi middleware token Pembawa JWT untuk memvalidasi token yang dikeluarkan oleh IdentityServer untuk aplikasi.
WeatherForecastController
Dalam file, perhatikan [Authorize]
atribut yang diterapkan ke kelas yang menunjukkan bahwa pengguna perlu diotorisasi berdasarkan kebijakan default untuk mengakses sumber daya. Kebijakan otorisasi default kebetulan dikonfigurasi untuk menggunakan skema autentikasi default, yang disiapkan oleh AddIdentityServerJwt
ke skema kebijakan yang disebutkan di atas, menjadikan JwtBearerHandler
dikonfigurasi oleh metode pembantu tersebut sebagai handler default untuk permintaan ke aplikasi.
ApplicationDbContext
Dalam file, perhatikan bahwa hal yang sama DbContext
digunakan dengan Identity pengecualian bahwa ia memperluas ApiAuthorizationDbContext
(kelas yang lebih turunan dari IdentityDbContext
) untuk menyertakan skema untuk IdentityServer.
Untuk mendapatkan kontrol penuh atas skema database, warisi dari salah satu kelas yang tersedia IdentityDbContext
dan konfigurasikan konteks untuk menyertakan Identity skema dengan memanggil builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value)
OnModelCreating
metode .
OidcConfigurationController
Dalam file, perhatikan titik akhir yang disediakan untuk melayani parameter OIDC yang perlu digunakan klien.
appsettings.json
appsettings.json
Dalam file akar proyek, ada bagian baru IdentityServer
yang menjelaskan daftar klien yang dikonfigurasi. Dalam contoh berikut, ada satu klien. Nama klien sesuai dengan nama aplikasi dan dipetakan berdasarkan konvensi ke parameter OAuth ClientId
. Profil menunjukkan jenis aplikasi yang sedang dikonfigurasi. Ini digunakan secara internal untuk mendorong konvensi yang menyederhanakan proses konfigurasi untuk server. Ada beberapa profil yang tersedia, seperti yang dijelaskan di bagian Profil aplikasi.
"IdentityServer": {
"Clients": {
"angularindividualpreview3final": {
"Profile": "IdentityServerSPA"
}
}
}
appsettings.Development.json
appsettings.Development.json
Dalam file akar proyek, ada IdentityServer
bagian yang menjelaskan kunci yang digunakan untuk menandatangani token. Saat menyebarkan ke produksi, kunci perlu disediakan dan disebarkan bersama aplikasi, seperti yang dijelaskan di bagian Sebarkan ke produksi .
"IdentityServer": {
"Key": {
"Type": "Development"
}
}
Deskripsi umum aplikasi Angular
Dukungan autentikasi dan otorisasi API dalam templat Angular berada dalam modul Angularnya sendiri di direktori ClientApp/src/api-authorization . Modul ini terdiri dari elemen-elemen berikut:
- 3 komponen:
login.component.ts
: Menangani alur masuk aplikasi.logout.component.ts
: Menangani alur keluar aplikasi.login-menu.component.ts
: Widget yang menampilkan salah satu set tautan berikut:- Manajemen profil pengguna dan tautan keluar saat pengguna diautentikasi.
- Tautan pendaftaran dan masuk saat pengguna tidak diautentikasi.
- Penjaga
AuthorizeGuard
rute yang dapat ditambahkan ke rute dan mengharuskan pengguna untuk diautentikasi sebelum mengunjungi rute. - Pencegat
AuthorizeInterceptor
HTTP yang melampirkan token akses ke permintaan HTTP keluar yang menargetkan API saat pengguna diautentikasi. - Layanan
AuthorizeService
yang menangani detail tingkat bawah proses autentikasi dan mengekspos informasi tentang pengguna yang diautentikasi ke aplikasi lainnya untuk dikonsumsi. - Modul Angular yang menentukan rute yang terkait dengan bagian autentikasi aplikasi. Ini mengekspos komponen menu login, pencegat, penjaga, dan layanan untuk dikonsumsi dari aplikasi lainnya.
Deskripsi umum aplikasi React
Dukungan untuk autentikasi dan otorisasi API di templat React berada di direktori ClientApp/src/components/api-authorization . Ini terdiri dari elemen-elemen berikut:
- 4 komponen:
Login.js
: Menangani alur masuk aplikasi.Logout.js
: Menangani alur keluar aplikasi.LoginMenu.js
: Widget yang menampilkan salah satu set tautan berikut:- Manajemen profil pengguna dan tautan keluar saat pengguna diautentikasi.
- Tautan pendaftaran dan masuk saat pengguna tidak diautentikasi.
AuthorizeRoute.js
: Komponen rute yang mengharuskan pengguna diautentikasi sebelum merender komponen yang ditunjukkan dalamComponent
parameter .
- Instans kelas
AuthorizeService
yang dieksporauthService
yang menangani detail tingkat bawah dari proses autentikasi dan mengekspos informasi tentang pengguna yang diautentikasi ke aplikasi lainnya untuk dikonsumsi.
Sekarang setelah Anda melihat komponen utama solusi, Anda dapat melihat skenario individual yang lebih dalam untuk aplikasi.
Memerlukan otorisasi pada API baru
Secara default, sistem dikonfigurasi untuk dengan mudah memerlukan otorisasi untuk API baru. Untuk melakukannya, buat pengontrol baru dan tambahkan [Authorize]
atribut ke kelas pengontrol atau ke tindakan apa pun dalam pengontrol.
Menyesuaikan handler autentikasi API
Untuk menyesuaikan konfigurasi handler JWT API, konfigurasikan instansnya JwtBearerOptions :
builder.Services.AddAuthentication()
.AddIdentityServerJwt();
builder.Services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
...
});
Handler JWT API meningkatkan peristiwa yang memungkinkan kontrol atas proses autentikasi menggunakan JwtBearerEvents
. Untuk memberikan dukungan untuk otorisasi API, AddIdentityServerJwt
daftarkan penanganan aktivitasnya sendiri.
Untuk menyesuaikan penanganan peristiwa, bungkus penanganan aktivitas yang ada dengan logika tambahan sesuai kebutuhan. Contohnya:
builder.Services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
var onTokenValidated = options.Events.OnTokenValidated;
options.Events.OnTokenValidated = async context =>
{
await onTokenValidated(context);
...
}
});
Dalam kode sebelumnya, penanganan OnTokenValidated
aktivitas diganti dengan implementasi kustom. Implementasi ini:
- Memanggil implementasi asli yang disediakan oleh dukungan otorisasi API.
- Jalankan logika kustomnya sendiri.
Melindungi rute sisi klien (Angular)
Melindungi rute sisi klien dilakukan dengan menambahkan penjaga otorisasi ke daftar penjaga yang akan dijalankan saat mengonfigurasi rute. Sebagai contoh, Anda dapat melihat bagaimana rute dikonfigurasi fetch-data
dalam modul Angular aplikasi utama:
RouterModule.forRoot([
// ...
{ path: 'fetch-data', component: FetchDataComponent, canActivate: [AuthorizeGuard] },
])
Penting untuk disebutkan bahwa melindungi rute tidak melindungi titik akhir aktual (yang masih memerlukan atribut yang [Authorize]
diterapkan padanya) tetapi hanya mencegah pengguna menavigasi ke rute sisi klien yang diberikan saat tidak diautentikasi.
Mengautentikasi permintaan API (Angular)
Mengautentikasi permintaan ke API yang dihosting bersama aplikasi dilakukan secara otomatis melalui penggunaan pencegat klien HTTP yang ditentukan oleh aplikasi.
Melindungi rute sisi klien (React)
Lindungi rute sisi klien dengan menggunakan AuthorizeRoute
komponen alih-alih komponen biasa Route
. Misalnya, perhatikan bagaimana rute dikonfigurasi fetch-data
dalam App
komponen:
<AuthorizeRoute path='/fetch-data' component={FetchData} />
Melindungi rute:
- Tidak melindungi titik akhir aktual (yang masih memerlukan atribut yang
[Authorize]
diterapkan padanya). - Hanya mencegah pengguna menavigasi ke rute sisi klien yang diberikan saat tidak diautentikasi.
Mengautentikasi permintaan API (React)
Mengautentikasi permintaan dengan React dilakukan dengan terlebih dahulu mengimpor authService
instans dari AuthorizeService
. Token akses diambil dari authService
dan dilampirkan ke permintaan seperti yang ditunjukkan di bawah ini. Dalam komponen React, pekerjaan ini biasanya dilakukan dalam componentDidMount
metode siklus hidup atau sebagai hasil dari beberapa interaksi pengguna.
Mengimpor ke authService
dalam komponen
import authService from './api-authorization/AuthorizeService'
Mengambil dan melampirkan token akses ke respons
async populateWeatherData() {
const token = await authService.getAccessToken();
const response = await fetch('api/SampleData/WeatherForecasts', {
headers: !token ? {} : { 'Authorization': `Bearer ${token}` }
});
const data = await response.json();
this.setState({ forecasts: data, loading: false });
}
Menyebarkan ke produksi
Untuk menyebarkan aplikasi ke produksi, sumber daya berikut perlu disediakan:
- Database untuk menyimpan Identity akun pengguna dan pemberian IdentityServer.
- Sertifikat produksi yang digunakan untuk menandatangani token.
- Tidak ada persyaratan khusus untuk sertifikat ini; dapat berupa sertifikat yang ditandatangani sendiri atau sertifikat yang disediakan melalui otoritas CA.
- Ini dapat dihasilkan melalui alat standar seperti PowerShell atau OpenSSL.
- Ini dapat diinstal ke penyimpanan sertifikat pada komputer target atau disebarkan sebagai file .pfx dengan kata sandi yang kuat.
Contoh: Menyebarkan ke penyedia hosting web non-Azure
Di panel hosting web Anda, buat atau muat sertifikat Anda. Kemudian dalam file aplikasi appsettings.json
, ubah bagian IdentityServer
untuk menyertakan detail utama. Contohnya:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "WebHosting",
"StoreLocation": "CurrentUser",
"Name": "CN=MyApplication"
}
}
Dalam contoh sebelumnya:
StoreName
mewakili nama penyimpanan sertifikat tempat sertifikat disimpan. Dalam hal ini, menunjuk ke penyimpanan hosting web.StoreLocation
mewakili tempat memuat sertifikat dari (CurrentUser
dalam hal ini).Name
sesuai dengan subjek khusus untuk sertifikat.
Contoh: Menyebarkan ke Azure App Service
Bagian ini menjelaskan penyebaran aplikasi ke Azure App Service menggunakan sertifikat yang disimpan di penyimpanan sertifikat. Untuk memodifikasi aplikasi untuk memuat sertifikat dari penyimpanan sertifikat, paket layanan tingkat Standar atau lebih baik diperlukan saat Anda mengonfigurasi aplikasi di portal Azure di langkah selanjutnya.
Dalam file aplikasi appsettings.json
, ubah bagian IdentityServer
untuk menyertakan detail utama:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "My",
"StoreLocation": "CurrentUser",
"Name": "CN=MyApplication"
}
}
- Nama penyimpanan mewakili nama penyimpanan sertifikat tempat sertifikat disimpan. Dalam hal ini, ini menunjuk ke penyimpanan pengguna pribadi.
- Lokasi penyimpanan mewakili tempat memuat sertifikat dari (
CurrentUser
atauLocalMachine
). - Properti nama pada sertifikat sesuai dengan subjek khusus untuk sertifikat.
Untuk menyebarkan ke Azure App Service, ikuti langkah-langkah dalam Menyebarkan aplikasi ke Azure, yang menjelaskan cara membuat sumber daya Azure yang diperlukan dan menyebarkan aplikasi ke produksi.
Setelah mengikuti instruksi sebelumnya, aplikasi disebarkan ke Azure tetapi belum berfungsi. Sertifikat yang digunakan oleh aplikasi harus dikonfigurasi di portal Azure. Temukan thumbprint untuk sertifikat dan ikuti langkah-langkah yang dijelaskan dalam Memuat sertifikat Anda.
Meskipun langkah-langkah ini menyebutkan SSL, ada bagian Sertifikat privat di portal Azure tempat Anda dapat mengunggah sertifikat yang disediakan untuk digunakan dengan aplikasi.
Setelah mengonfigurasi aplikasi dan pengaturan aplikasi di portal Azure, mulai ulang aplikasi di portal.
Opsi konfigurasi lainnya
Dukungan untuk otorisasi API dibangun di atas IdentityServer dengan serangkaian konvensi, nilai default, dan penyempurnaan untuk menyederhanakan pengalaman untuk SPAs. Tidak perlu dikatakan, kekuatan Identitypenuh Server tersedia di belakang layar jika integrasi ASP.NET Core tidak mencakup skenario Anda. Dukungan ASP.NET Core difokuskan pada aplikasi "pihak pertama", tempat semua aplikasi dibuat dan disebarkan oleh organisasi kami. Dengan demikian, dukungan tidak ditawarkan untuk hal-hal seperti persetujuan atau federasi. Untuk skenario tersebut, gunakan IdentityServer dan ikuti dokumentasinya.
Profil aplikasi
Profil aplikasi adalah konfigurasi yang telah ditentukan sebelumnya untuk aplikasi yang lebih menentukan parameternya. Saat ini, profil berikut didukung:
IdentityServerSPA
: Mewakili SPA yang dihosting Identitybersama Server sebagai satu unit.- Default
redirect_uri
ke/authentication/login-callback
. - Default
post_logout_redirect_uri
ke/authentication/logout-callback
. - Kumpulan cakupan mencakup
openid
, ,profile
dan setiap cakupan yang ditentukan untuk API di aplikasi. - Kumpulan jenis respons OIDC yang diizinkan adalah
id_token token
atau masing-masing secara individual (id_token
,token
). - Mode respons yang diizinkan adalah
fragment
.
- Default
SPA
: Mewakili SPA yang tidak dihosting dengan IdentityServer.- Kumpulan cakupan mencakup
openid
, ,profile
dan setiap cakupan yang ditentukan untuk API di aplikasi. - Kumpulan jenis respons OIDC yang diizinkan adalah
id_token token
atau masing-masing secara individual (id_token
,token
). - Mode respons yang diizinkan adalah
fragment
.
- Kumpulan cakupan mencakup
IdentityServerJwt
: Mewakili API yang dihosting bersama dengan IdentityServer.- Aplikasi ini dikonfigurasi untuk memiliki satu cakupan yang default ke nama aplikasi.
API
: Mewakili API yang tidak dihosting dengan IdentityServer.- Aplikasi ini dikonfigurasi untuk memiliki satu cakupan yang default ke nama aplikasi.
Konfigurasi melalui AppSettings
Konfigurasikan aplikasi melalui sistem konfigurasi dengan menambahkannya ke daftar Clients
atau Resources
.
Konfigurasikan setiap klien redirect_uri
dan post_logout_redirect_uri
properti, seperti yang ditunjukkan dalam contoh berikut:
"IdentityServer": {
"Clients": {
"MySPA": {
"Profile": "SPA",
"RedirectUri": "https://www.example.com/authentication/login-callback",
"LogoutUri": "https://www.example.com/authentication/logout-callback"
}
}
}
Saat mengonfigurasi sumber daya, Anda dapat mengonfigurasi cakupan untuk sumber daya seperti yang ditunjukkan di bawah ini:
"IdentityServer": {
"Resources": {
"MyExternalApi": {
"Profile": "API",
"Scopes": "a b c"
}
}
}
Konfigurasi melalui kode
Anda juga dapat mengonfigurasi klien dan sumber daya melalui kode menggunakan kelebihan beban AddApiAuthorization
yang mengambil tindakan untuk mengonfigurasi opsi.
AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
options.Clients.AddSPA(
"My SPA", spa =>
spa.WithRedirectUri("http://www.example.com/authentication/login-callback")
.WithLogoutRedirectUri(
"http://www.example.com/authentication/logout-callback"));
options.ApiResources.AddApiResource("MyExternalApi", resource =>
resource.WithScopes("a", "b", "c"));
});
Sumber Daya Tambahan:
Templat ASP.NET Core 3.1 dan yang lebih baru menawarkan autentikasi di Aplikasi Halaman Tunggal (SPAs) menggunakan dukungan untuk otorisasi API. ASP.NET Core Identity untuk mengautentikasi dan menyimpan pengguna dikombinasikan dengan IdentityServer untuk menerapkan Koneksi OpenID.
Parameter autentikasi ditambahkan ke templat proyek Angular dan React yang mirip dengan parameter autentikasi di templat proyek Aplikasi Web (Model-View-Controller) (MVC) dan Aplikasi Web (Razor Halaman). Nilai parameter yang diizinkan adalah Tidak Ada dan Individual. Templat proyek React.js dan Redux saat ini tidak mendukung parameter autentikasi.
Membuat aplikasi dengan dukungan otorisasi API
Autentikasi dan otorisasi pengguna dapat digunakan dengan Angular dan React SPAs. Buka shell perintah, dan jalankan perintah berikut:
Sudut:
dotnet new angular -o <output_directory_name>
React:
dotnet new react -o <output_directory_name> -au Individual
Perintah sebelumnya membuat aplikasi ASP.NET Core dengan direktori ClientApp yang berisi SPA.
Deskripsi umum komponen ASP.NET Core aplikasi
Bagian berikut menjelaskan penambahan ke proyek saat dukungan autentikasi disertakan:
Startup
kelas
Contoh kode berikut mengandalkan Microsoft.AspNetCore.ApiAuthorization.IdentityPaket NuGet Server . Contoh mengonfigurasi autentikasi dan otorisasi API menggunakan AddApiAuthorization metode ekstensi dan AddIdentityServerJwt . Proyek yang menggunakan templat proyek React atau Angular SPA dengan autentikasi menyertakan referensi ke paket ini.
Kelas Startup
memiliki penambahan berikut:
Startup.ConfigureServices
Di dalam metode :Identity dengan UI default:
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlite(Configuration.GetConnectionString("DefaultConnection"))); services.AddDefaultIdentity<ApplicationUser>() .AddEntityFrameworkStores<ApplicationDbContext>();
IdentityServer dengan metode pembantu Identitytambahan
AddApiAuthorization
yang menyiapkan beberapa konvensi ASP.NET Core default di atas Server:services.AddIdentityServer() .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
Autentikasi dengan metode pembantu tambahan
AddIdentityServerJwt
yang mengonfigurasi aplikasi untuk memvalidasi token JWT yang diproduksi oleh IdentityServer:services.AddAuthentication() .AddIdentityServerJwt();
Startup.Configure
Di dalam metode :Middleware autentikasi yang bertanggung jawab untuk memvalidasi kredensial permintaan dan mengatur pengguna pada konteks permintaan:
app.UseAuthentication();
IdentityMiddleware Server yang mengekspos titik akhir Koneksi OpenID:
app.UseIdentityServer();
Azure App Service di Linux
Untuk penyebaran Azure App Service di Linux, tentukan penerbit secara eksplisit di Startup.ConfigureServices
:
services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
options.Authority = "{AUTHORITY}";
});
Dalam kode sebelumnya, {AUTHORITY}
tempat penampung adalah Authority untuk digunakan saat melakukan panggilan Koneksi OpenID.
Contoh:
options.Authority = "https://contoso-service.azurewebsites.net";
AddApiAuthorization
Metode pembantu Identityini mengonfigurasi Server untuk menggunakan konfigurasi kami yang didukung. IdentityServer adalah kerangka kerja yang kuat dan dapat diperluas untuk menangani masalah keamanan aplikasi. Pada saat yang sama, yang mengekspos kompleksitas yang tidak perlu untuk skenario yang paling umum. Akibatnya, serangkaian konvensi dan opsi konfigurasi disediakan untuk Anda yang dianggap sebagai titik awal yang baik. Setelah autentikasi Anda perlu berubah, kekuatan Identitypenuh Server masih tersedia untuk menyesuaikan autentikasi agar sesuai dengan kebutuhan Anda.
AddIdentityServerJwt
Metode pembantu ini mengonfigurasi skema kebijakan untuk aplikasi sebagai penangan autentikasi default. Kebijakan dikonfigurasi untuk memungkinkan Identity menangani semua permintaan yang dirutekan ke subpath apa pun di Identity ruang URL "/Identity". Menangani JwtBearerHandler
semua permintaan lainnya. Selain itu, metode ini mendaftarkan <<ApplicationName>>API
sumber daya API dengan IdentityServer dengan cakupan <<ApplicationName>>API
default dan mengonfigurasi middleware token Pembawa JWT untuk memvalidasi token yang dikeluarkan oleh IdentityServer untuk aplikasi.
WeatherForecastController
Dalam file, perhatikan [Authorize]
atribut yang diterapkan ke kelas yang menunjukkan bahwa pengguna perlu diotorisasi berdasarkan kebijakan default untuk mengakses sumber daya. Kebijakan otorisasi default kebetulan dikonfigurasi untuk menggunakan skema autentikasi default, yang disiapkan oleh AddIdentityServerJwt
ke skema kebijakan yang disebutkan di atas, menjadikan JwtBearerHandler
dikonfigurasi oleh metode pembantu tersebut sebagai handler default untuk permintaan ke aplikasi.
ApplicationDbContext
Dalam file, perhatikan bahwa hal yang sama DbContext
digunakan dengan Identity pengecualian bahwa ia memperluas ApiAuthorizationDbContext
(kelas yang lebih turunan dari IdentityDbContext
) untuk menyertakan skema untuk IdentityServer.
Untuk mendapatkan kontrol penuh atas skema database, warisi dari salah satu kelas yang tersedia IdentityDbContext
dan konfigurasikan konteks untuk menyertakan Identity skema dengan memanggil builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value)
OnModelCreating
metode .
OidcConfigurationController
Dalam file, perhatikan titik akhir yang disediakan untuk melayani parameter OIDC yang perlu digunakan klien.
appsettings.json
appsettings.json
Dalam file akar proyek, ada bagian baru IdentityServer
yang menjelaskan daftar klien yang dikonfigurasi. Dalam contoh berikut, ada satu klien. Nama klien sesuai dengan nama aplikasi dan dipetakan berdasarkan konvensi ke parameter OAuth ClientId
. Profil menunjukkan jenis aplikasi yang sedang dikonfigurasi. Ini digunakan secara internal untuk mendorong konvensi yang menyederhanakan proses konfigurasi untuk server. Ada beberapa profil yang tersedia, seperti yang dijelaskan di bagian Profil aplikasi.
"IdentityServer": {
"Clients": {
"angularindividualpreview3final": {
"Profile": "IdentityServerSPA"
}
}
}
appsettings.Development.json
appsettings.Development.json
Dalam file akar proyek, ada IdentityServer
bagian yang menjelaskan kunci yang digunakan untuk menandatangani token. Saat menyebarkan ke produksi, kunci perlu disediakan dan disebarkan bersama aplikasi, seperti yang dijelaskan di bagian Sebarkan ke produksi .
"IdentityServer": {
"Key": {
"Type": "Development"
}
}
Deskripsi umum aplikasi Angular
Dukungan autentikasi dan otorisasi API dalam templat Angular berada dalam modul Angularnya sendiri di direktori ClientApp/src/api-authorization . Modul ini terdiri dari elemen-elemen berikut:
- 3 komponen:
login.component.ts
: Menangani alur masuk aplikasi.logout.component.ts
: Menangani alur keluar aplikasi.login-menu.component.ts
: Widget yang menampilkan salah satu set tautan berikut:- Manajemen profil pengguna dan tautan keluar saat pengguna diautentikasi.
- Tautan pendaftaran dan masuk saat pengguna tidak diautentikasi.
- Penjaga
AuthorizeGuard
rute yang dapat ditambahkan ke rute dan mengharuskan pengguna untuk diautentikasi sebelum mengunjungi rute. - Pencegat
AuthorizeInterceptor
HTTP yang melampirkan token akses ke permintaan HTTP keluar yang menargetkan API saat pengguna diautentikasi. - Layanan
AuthorizeService
yang menangani detail tingkat bawah proses autentikasi dan mengekspos informasi tentang pengguna yang diautentikasi ke aplikasi lainnya untuk dikonsumsi. - Modul Angular yang menentukan rute yang terkait dengan bagian autentikasi aplikasi. Ini mengekspos komponen menu login, pencegat, penjaga, dan layanan untuk dikonsumsi dari aplikasi lainnya.
Deskripsi umum aplikasi React
Dukungan untuk autentikasi dan otorisasi API di templat React berada di direktori ClientApp/src/components/api-authorization . Ini terdiri dari elemen-elemen berikut:
- 4 komponen:
Login.js
: Menangani alur masuk aplikasi.Logout.js
: Menangani alur keluar aplikasi.LoginMenu.js
: Widget yang menampilkan salah satu set tautan berikut:- Manajemen profil pengguna dan tautan keluar saat pengguna diautentikasi.
- Tautan pendaftaran dan masuk saat pengguna tidak diautentikasi.
AuthorizeRoute.js
: Komponen rute yang mengharuskan pengguna diautentikasi sebelum merender komponen yang ditunjukkan dalamComponent
parameter .
- Instans kelas
AuthorizeService
yang dieksporauthService
yang menangani detail tingkat bawah dari proses autentikasi dan mengekspos informasi tentang pengguna yang diautentikasi ke aplikasi lainnya untuk dikonsumsi.
Sekarang setelah Anda melihat komponen utama solusi, Anda dapat melihat skenario individual yang lebih dalam untuk aplikasi.
Memerlukan otorisasi pada API baru
Secara default, sistem dikonfigurasi untuk dengan mudah memerlukan otorisasi untuk API baru. Untuk melakukannya, buat pengontrol baru dan tambahkan [Authorize]
atribut ke kelas pengontrol atau ke tindakan apa pun dalam pengontrol.
Menyesuaikan handler autentikasi API
Untuk menyesuaikan konfigurasi handler JWT API, konfigurasikan instansnya JwtBearerOptions :
services.AddAuthentication()
.AddIdentityServerJwt();
services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
...
});
Handler JWT API meningkatkan peristiwa yang memungkinkan kontrol atas proses autentikasi menggunakan JwtBearerEvents
. Untuk memberikan dukungan untuk otorisasi API, AddIdentityServerJwt
daftarkan penanganan aktivitasnya sendiri.
Untuk menyesuaikan penanganan peristiwa, bungkus penanganan aktivitas yang ada dengan logika tambahan sesuai kebutuhan. Contohnya:
services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
var onTokenValidated = options.Events.OnTokenValidated;
options.Events.OnTokenValidated = async context =>
{
await onTokenValidated(context);
...
}
});
Dalam kode sebelumnya, penanganan OnTokenValidated
aktivitas diganti dengan implementasi kustom. Implementasi ini:
- Memanggil implementasi asli yang disediakan oleh dukungan otorisasi API.
- Jalankan logika kustomnya sendiri.
Melindungi rute sisi klien (Angular)
Melindungi rute sisi klien dilakukan dengan menambahkan penjaga otorisasi ke daftar penjaga yang akan dijalankan saat mengonfigurasi rute. Sebagai contoh, Anda dapat melihat bagaimana rute dikonfigurasi fetch-data
dalam modul Angular aplikasi utama:
RouterModule.forRoot([
// ...
{ path: 'fetch-data', component: FetchDataComponent, canActivate: [AuthorizeGuard] },
])
Penting untuk disebutkan bahwa melindungi rute tidak melindungi titik akhir aktual (yang masih memerlukan atribut yang [Authorize]
diterapkan padanya) tetapi hanya mencegah pengguna menavigasi ke rute sisi klien yang diberikan saat tidak diautentikasi.
Mengautentikasi permintaan API (Angular)
Mengautentikasi permintaan ke API yang dihosting bersama aplikasi dilakukan secara otomatis melalui penggunaan pencegat klien HTTP yang ditentukan oleh aplikasi.
Melindungi rute sisi klien (React)
Lindungi rute sisi klien dengan menggunakan AuthorizeRoute
komponen alih-alih komponen biasa Route
. Misalnya, perhatikan bagaimana rute dikonfigurasi fetch-data
dalam App
komponen:
<AuthorizeRoute path='/fetch-data' component={FetchData} />
Melindungi rute:
- Tidak melindungi titik akhir aktual (yang masih memerlukan atribut yang
[Authorize]
diterapkan padanya). - Hanya mencegah pengguna menavigasi ke rute sisi klien yang diberikan saat tidak diautentikasi.
Mengautentikasi permintaan API (React)
Mengautentikasi permintaan dengan React dilakukan dengan terlebih dahulu mengimpor authService
instans dari AuthorizeService
. Token akses diambil dari authService
dan dilampirkan ke permintaan seperti yang ditunjukkan di bawah ini. Dalam komponen React, pekerjaan ini biasanya dilakukan dalam componentDidMount
metode siklus hidup atau sebagai hasil dari beberapa interaksi pengguna.
Mengimpor ke authService
dalam komponen
import authService from './api-authorization/AuthorizeService'
Mengambil dan melampirkan token akses ke respons
async populateWeatherData() {
const token = await authService.getAccessToken();
const response = await fetch('api/SampleData/WeatherForecasts', {
headers: !token ? {} : { 'Authorization': `Bearer ${token}` }
});
const data = await response.json();
this.setState({ forecasts: data, loading: false });
}
Menyebarkan ke produksi
Untuk menyebarkan aplikasi ke produksi, sumber daya berikut perlu disediakan:
- Database untuk menyimpan Identity akun pengguna dan pemberian IdentityServer.
- Sertifikat produksi yang digunakan untuk menandatangani token.
- Tidak ada persyaratan khusus untuk sertifikat ini; dapat berupa sertifikat yang ditandatangani sendiri atau sertifikat yang disediakan melalui otoritas CA.
- Ini dapat dihasilkan melalui alat standar seperti PowerShell atau OpenSSL.
- Ini dapat diinstal ke penyimpanan sertifikat pada komputer target atau disebarkan sebagai file .pfx dengan kata sandi yang kuat.
Contoh: Menyebarkan ke penyedia hosting web non-Azure
Di panel hosting web Anda, buat atau muat sertifikat Anda. Kemudian dalam file aplikasi appsettings.json
, ubah bagian IdentityServer
untuk menyertakan detail utama. Contohnya:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "WebHosting",
"StoreLocation": "CurrentUser",
"Name": "CN=MyApplication"
}
}
Dalam contoh sebelumnya:
StoreName
mewakili nama penyimpanan sertifikat tempat sertifikat disimpan. Dalam hal ini, menunjuk ke penyimpanan hosting web.StoreLocation
mewakili tempat memuat sertifikat dari (CurrentUser
dalam hal ini).Name
sesuai dengan subjek khusus untuk sertifikat.
Contoh: Menyebarkan ke Azure App Service
Bagian ini menjelaskan penyebaran aplikasi ke Azure App Service menggunakan sertifikat yang disimpan di penyimpanan sertifikat. Untuk memodifikasi aplikasi untuk memuat sertifikat dari penyimpanan sertifikat, paket layanan tingkat Standar atau lebih baik diperlukan saat Anda mengonfigurasi aplikasi di portal Azure di langkah selanjutnya.
Dalam file aplikasi appsettings.json
, ubah bagian IdentityServer
untuk menyertakan detail utama:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "My",
"StoreLocation": "CurrentUser",
"Name": "CN=MyApplication"
}
}
- Nama penyimpanan mewakili nama penyimpanan sertifikat tempat sertifikat disimpan. Dalam hal ini, ini menunjuk ke penyimpanan pengguna pribadi.
- Lokasi penyimpanan mewakili tempat memuat sertifikat dari (
CurrentUser
atauLocalMachine
). - Properti nama pada sertifikat sesuai dengan subjek khusus untuk sertifikat.
Untuk menyebarkan ke Azure App Service, ikuti langkah-langkah dalam Menyebarkan aplikasi ke Azure, yang menjelaskan cara membuat sumber daya Azure yang diperlukan dan menyebarkan aplikasi ke produksi.
Setelah mengikuti instruksi sebelumnya, aplikasi disebarkan ke Azure tetapi belum berfungsi. Sertifikat yang digunakan oleh aplikasi harus dikonfigurasi di portal Azure. Temukan thumbprint untuk sertifikat dan ikuti langkah-langkah yang dijelaskan dalam Memuat sertifikat Anda.
Meskipun langkah-langkah ini menyebutkan SSL, ada bagian Sertifikat privat di portal Azure tempat Anda dapat mengunggah sertifikat yang disediakan untuk digunakan dengan aplikasi.
Setelah mengonfigurasi aplikasi dan pengaturan aplikasi di portal Azure, mulai ulang aplikasi di portal.
Opsi konfigurasi lainnya
Dukungan untuk otorisasi API dibangun di atas IdentityServer dengan serangkaian konvensi, nilai default, dan penyempurnaan untuk menyederhanakan pengalaman untuk SPAs. Tidak perlu dikatakan, kekuatan Identitypenuh Server tersedia di belakang layar jika integrasi ASP.NET Core tidak mencakup skenario Anda. Dukungan ASP.NET Core difokuskan pada aplikasi "pihak pertama", tempat semua aplikasi dibuat dan disebarkan oleh organisasi kami. Dengan demikian, dukungan tidak ditawarkan untuk hal-hal seperti persetujuan atau federasi. Untuk skenario tersebut, gunakan IdentityServer dan ikuti dokumentasinya.
Profil aplikasi
Profil aplikasi adalah konfigurasi yang telah ditentukan sebelumnya untuk aplikasi yang lebih menentukan parameternya. Saat ini, profil berikut didukung:
IdentityServerSPA
: Mewakili SPA yang dihosting Identitybersama Server sebagai satu unit.- Default
redirect_uri
ke/authentication/login-callback
. - Default
post_logout_redirect_uri
ke/authentication/logout-callback
. - Kumpulan cakupan mencakup
openid
, ,profile
dan setiap cakupan yang ditentukan untuk API di aplikasi. - Kumpulan jenis respons OIDC yang diizinkan adalah
id_token token
atau masing-masing secara individual (id_token
,token
). - Mode respons yang diizinkan adalah
fragment
.
- Default
SPA
: Mewakili SPA yang tidak dihosting dengan IdentityServer.- Kumpulan cakupan mencakup
openid
, ,profile
dan setiap cakupan yang ditentukan untuk API di aplikasi. - Kumpulan jenis respons OIDC yang diizinkan adalah
id_token token
atau masing-masing secara individual (id_token
,token
). - Mode respons yang diizinkan adalah
fragment
.
- Kumpulan cakupan mencakup
IdentityServerJwt
: Mewakili API yang dihosting bersama dengan IdentityServer.- Aplikasi ini dikonfigurasi untuk memiliki satu cakupan yang default ke nama aplikasi.
API
: Mewakili API yang tidak dihosting dengan IdentityServer.- Aplikasi ini dikonfigurasi untuk memiliki satu cakupan yang default ke nama aplikasi.
Konfigurasi melalui AppSettings
Konfigurasikan aplikasi melalui sistem konfigurasi dengan menambahkannya ke daftar Clients
atau Resources
.
Konfigurasikan setiap klien redirect_uri
dan post_logout_redirect_uri
properti, seperti yang ditunjukkan dalam contoh berikut:
"IdentityServer": {
"Clients": {
"MySPA": {
"Profile": "SPA",
"RedirectUri": "https://www.example.com/authentication/login-callback",
"LogoutUri": "https://www.example.com/authentication/logout-callback"
}
}
}
Saat mengonfigurasi sumber daya, Anda dapat mengonfigurasi cakupan untuk sumber daya seperti yang ditunjukkan di bawah ini:
"IdentityServer": {
"Resources": {
"MyExternalApi": {
"Profile": "API",
"Scopes": "a b c"
}
}
}
Konfigurasi melalui kode
Anda juga dapat mengonfigurasi klien dan sumber daya melalui kode menggunakan kelebihan beban AddApiAuthorization
yang mengambil tindakan untuk mengonfigurasi opsi.
AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
options.Clients.AddSPA(
"My SPA", spa =>
spa.WithRedirectUri("http://www.example.com/authentication/login-callback")
.WithLogoutRedirectUri(
"http://www.example.com/authentication/logout-callback"));
options.ApiResources.AddApiResource("MyExternalApi", resource =>
resource.WithScopes("a", "b", "c"));
});
Sumber Daya Tambahan:
ASP.NET Core
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk