Pengelolaan status dan sesi di ASP.NET Core
Oleh Rick Anderson, Kirk Larkin, dan Diana LaRose
HTTP adalah protokol stateless. Secara default, permintaan HTTP adalah pesan independen yang tidak mempertahankan nilai pengguna. Artikel ini menjelaskan beberapa pendekatan untuk mempertahankan data pengguna antar permintaan.
Untuk Blazor panduan manajemen status, yang menambahkan atau menggantikan panduan dalam artikel ini, lihat ASP.NET manajemen status IntiBlazor.
Manajemen Status
Status dapat disimpan menggunakan beberapa pendekatan. Setiap pendekatan dijelaskan nanti dalam artikel ini.
Pendekatan penyimpanan | Mekanisme penyimpanan |
---|---|
Cookie | Cookie HTTP. Dapat mencakup data yang disimpan menggunakan kode aplikasi sisi server. |
Status sesi | Cookie HTTP dan kode aplikasi sisi server |
TempData | Cookie HTTP atau status sesi |
String kueri | String kueri HTTP |
Bidang tersembunyi | Bidang formulir HTTP |
HttpContext.Items | Kode aplikasi sisi server |
Cache | Kode aplikasi sisi server |
SignalR/Blazor Server dan manajemen status berbasis konteks HTTP
SignalR aplikasi tidak boleh menggunakan status sesi dan pendekatan manajemen status lainnya yang mengandalkan konteks HTTP yang stabil untuk menyimpan informasi. SignalR aplikasi dapat menyimpan status per koneksi di Context.Items
hub. Untuk informasi selengkapnya dan pendekatan manajemen status alternatif untuk Blazor Server aplikasi, lihat manajemen status ASP.NET CoreBlazor.
Cookie
Cookie menyimpan data di seluruh permintaan. Karena cookie dikirim dengan setiap permintaan, ukurannya harus dijaga seminimal mungkin. Idealnya, hanya pengidentifikasi yang harus disimpan dalam dengan data yang cookie disimpan oleh aplikasi. Sebagian besar browser membatasi cookie ukuran hingga 4096 byte. Hanya sejumlah cookie terbatas yang tersedia untuk setiap domain.
Karena cookie dapat diubah, cookie harus divalidasi oleh aplikasi. Cookie dapat dihapus oleh pengguna dan kedaluwarsa pada klien. Namun, cookie umumnya merupakan bentuk persistensi data yang paling tahan lama pada klien.
Cookie sering digunakan untuk personalisasi, di mana konten disesuaikan untuk pengguna yang dikenal. Pengguna hanya diidentifikasi dan tidak diautentikasi dalam banyak kasus. cookie dapat menyimpan nama pengguna, nama akun, atau ID pengguna unik seperti GUID. cookie dapat digunakan untuk mengakses pengaturan yang dipersonalisasi pengguna, seperti warna latar belakang situs web pilihan mereka.
Lihat Peraturan Perlindungan Data Umum Uni Eropa (GDPR) saat mengeluarkan cookie dan berurusan dengan privacy masalah. Untuk informasi selengkapnya, lihat Dukungan Peraturan Perlindungan Data Umum (GDPR) di ASP.NET Core.
Status sesi
Status sesi adalah skenario ASP.NET Core untuk penyimpanan data pengguna saat pengguna menelusuri aplikasi web. Status sesi menggunakan penyimpanan yang dikelola oleh aplikasi untuk mempertahankan data di seluruh permintaan dari klien. Data sesi didukung oleh cache dan dianggap sebagai data ephemeral. Situs harus terus berfungsi tanpa data sesi. Data aplikasi penting harus disimpan dalam database pengguna dan di-cache dalam sesi hanya sebagai pengoptimalan performa.
Sesi tidak didukung di SignalR aplikasi karena SignalR Hub dapat menjalankan independen dari konteks HTTP. Misalnya, ini dapat terjadi ketika permintaan polling panjang ditahan terbuka oleh hub di luar masa pakai konteks HTTP permintaan.
ASP.NET Core mempertahankan status sesi dengan memberikan cookie kepada klien yang berisi ID sesi. cookie ID sesi:
- Dikirim ke aplikasi dengan setiap permintaan.
- Digunakan oleh aplikasi untuk mengambil data sesi.
Status sesi menunjukkan perilaku berikut:
- Sesi cookie ini khusus untuk browser. Sesi tidak dibagikan di seluruh browser.
- Cookie sesi dihapus ketika sesi browser berakhir.
- cookie Jika diterima untuk sesi yang kedaluwarsa, sesi baru dibuat yang menggunakan sesi cookieyang sama .
- Sesi kosong tidak dipertahankan. Sesi harus memiliki setidaknya satu nilai yang diatur untuk mempertahankan sesi di seluruh permintaan. Saat sesi tidak dipertahankan, ID sesi baru dibuat untuk setiap permintaan baru.
- Aplikasi mempertahankan sesi untuk waktu yang terbatas setelah permintaan terakhir. Aplikasi mengatur batas waktu sesi atau menggunakan nilai default 20 menit. Status sesi sangat ideal untuk menyimpan data pengguna:
- Itu khusus untuk sesi tertentu.
- Jika data tidak memerlukan penyimpanan permanen di seluruh sesi.
- Data sesi dihapus baik ketika implementasi dipanggil ISession.Clear atau ketika sesi kedaluwarsa.
- Tidak ada mekanisme default untuk menginformasikan kode aplikasi bahwa browser klien telah ditutup atau ketika sesi cookie dihapus atau kedaluwarsa pada klien.
- Cookie status sesi tidak ditandai penting secara default. Status sesi tidak berfungsi kecuali pelacakan diizinkan oleh pengunjung situs. Untuk informasi selengkapnya, lihat Dukungan Peraturan Perlindungan Data Umum (GDPR) di ASP.NET Core.
- Catatan: Tidak ada penggantian untuk fitur sesi tanpa cookie dari ASP.NET Framework karena dianggap tidak aman dan dapat menyebabkan serangan fiksasi sesi.
Peringatan
Jangan simpan data sensitif dalam status sesi. Pengguna mungkin tidak menutup browser dan menghapus sesi cookie. Beberapa browser mempertahankan cookie sesi yang valid di seluruh jendela browser. Sesi mungkin tidak dibatasi untuk satu pengguna. Pengguna berikutnya mungkin terus menelusuri aplikasi dengan sesi cookieyang sama.
Penyedia cache dalam memori menyimpan data sesi dalam memori server tempat aplikasi berada. Dalam skenario farm server:
- Gunakan sesi lekat untuk mengikat setiap sesi ke instans aplikasi tertentu di server individual. Azure App Service menggunakan Perutean Permintaan Aplikasi (ARR) untuk menerapkan sesi lekat secara default. Namun, sesi lengket dapat memengaruhi skalabilitas dan mempersulit pembaruan aplikasi web. Pendekatan yang lebih baik adalah menggunakan cache terdistribusi Redis atau SQL Server, yang tidak memerlukan sesi lengket. Untuk informasi selengkapnya, lihat Penembolokan terdistribusi di ASP.NET Core.
- Sesi cookie dienkripsi melalui IDataProtector. Perlindungan Data harus dikonfigurasi dengan benar untuk membaca cookie sesi pada setiap komputer. Untuk informasi selengkapnya, lihat Gambaran Umum Perlindungan Data Inti ASP.NET dan Penyedia penyimpanan Kunci.
Mengonfigurasi status sesi
Middleware untuk mengelola status sesi disertakan dalam kerangka kerja. Untuk mengaktifkan middleware sesi, Program.cs
harus berisi:
- IDistributedCache Salah satu cache memori. Implementasi
IDistributedCache
digunakan sebagai penyimpanan backing untuk sesi. Untuk informasi selengkapnya, lihat Penembolokan terdistribusi di ASP.NET Core. - Panggilan ke AddSession
- Panggilan ke UseSession
Kode berikut menunjukkan cara menyiapkan penyedia sesi dalam memori dengan implementasi dalam memori default dari IDistributedCache
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseSession();
app.MapRazorPages();
app.MapDefaultControllerRoute();
app.Run();
Kode sebelumnya menetapkan batas waktu yang singkat untuk menyederhanakan pengujian.
Urutan middleware penting. Hubungi UseSession
setelah UseRouting
dan sebelum MapRazorPages
dan MapDefaultControllerRoute
. Lihat Pemesanan Middleware.
HttpContext.Session tersedia setelah status sesi dikonfigurasi.
HttpContext.Session
tidak dapat diakses sebelumnya UseSession
telah dipanggil.
Sesi baru dengan sesi cookie baru tidak dapat dibuat setelah aplikasi mulai menulis ke aliran respons. Pengecualian direkam di log server web dan tidak ditampilkan di browser.
Memuat status sesi secara asinkron
Penyedia sesi default di ASP.NET Core memuat rekaman sesi dari penyimpanan pendukung yang mendasar IDistributedCache secara asinkron hanya jika ISession.LoadAsync metode secara eksplisit dipanggil sebelum TryGetValuemetode , , Setatau Remove . Jika LoadAsync
tidak dipanggil terlebih dahulu, rekaman sesi yang mendasar dimuat secara sinkron, yang dapat dikenakan penalti performa dalam skala besar.
Agar aplikasi menerapkan pola ini, bungkus DistributedSessionStore implementasi dan DistributedSession dengan versi yang melemparkan pengecualian jika LoadAsync
metode tidak dipanggil sebelum TryGetValue
, , Set
atau Remove
. Daftarkan versi yang dibungkus dalam kontainer layanan.
Opsi sesi
Untuk mengambil alih default sesi, gunakan SessionOptions.
Opsi | Deskripsi |
---|---|
Cookie | Menentukan pengaturan yang digunakan untuk membuat cookie. Name default ke SessionDefaults.CookieName (.AspNetCore.Session ). Path default ke SessionDefaults.CookiePath (/ ). SameSite default ke SameSiteMode.Lax (1 ). HttpOnly defaultnya adalah true . IsEssential defaultnya adalah false . |
IdleTimeout | menunjukkan IdleTimeout berapa lama sesi dapat diam sebelum kontennya ditinggalkan. Setiap akses sesi mengatur ulang batas waktu. Pengaturan ini hanya berlaku untuk konten sesi, bukan cookie. Defaultnya adalah 20 menit. |
IOTimeout | Jumlah waktu maksimum yang diizinkan untuk memuat sesi dari penyimpanan atau untuk menerapkannya kembali ke penyimpanan. Pengaturan ini mungkin hanya berlaku untuk operasi asinkron. Batas waktu ini dapat dinonaktifkan menggunakan InfiniteTimeSpan. Defaultnya adalah 1 menit. |
Sesi menggunakan cookie untuk melacak dan mengidentifikasi permintaan dari satu browser. Secara default, ini cookie bernama .AspNetCore.Session
, dan menggunakan jalur /
. cookie Karena default tidak menentukan domain, domain tidak tersedia untuk skrip sisi klien di halaman (karena HttpOnly default ke true
).
Untuk mengambil alih cookie default sesi, gunakan SessionOptions:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession(options =>
{
options.Cookie.Name = ".AdventureWorks.Session";
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.IsEssential = true;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseSession();
app.MapRazorPages();
app.MapDefaultControllerRoute();
app.Run();
Aplikasi ini menggunakan IdleTimeout properti untuk menentukan berapa lama sesi dapat menganggur sebelum kontennya di cache server ditinggalkan. Properti ini tidak bergantung pada kedaluwarsa cookie . Setiap permintaan yang melewati Middleware Sesi mengatur ulang batas waktu.
Status sesi tidak terkunci. Jika dua permintaan secara bersamaan mencoba memodifikasi konten sesi, permintaan terakhir akan mengambil alih yang pertama. Session
diimplementasikan sebagai sesi yang koheren, yang berarti bahwa semua konten disimpan bersama-sama. Ketika dua permintaan berusaha mengubah nilai sesi yang berbeda, permintaan terakhir dapat mengambil alih perubahan sesi yang dibuat oleh yang pertama.
Mengatur dan mendapatkan nilai Sesi
Status sesi diakses dari Razor kelas Pages PageModel atau kelas MVC Controller dengan HttpContext.Session. Properti ini adalah ISession implementasi.
Implementasi ini ISession
menyediakan beberapa metode ekstensi untuk mengatur dan mengambil nilai bilangan bulat dan string. Metode ekstensi berada di Microsoft.AspNetCore.Http namespace layanan.
ISession
metode ekstensi:
- Get(ISession, String)
- GetInt32(ISession, String)
- GetString(ISession, String)
- SetInt32(ISession, String, Int32)
- SetString(ISession, String, String)
Contoh berikut mengambil nilai sesi untuk IndexModel.SessionKeyName
kunci (_Name
di aplikasi sampel) di Razor halaman Halaman:
@page
@using Microsoft.AspNetCore.Http
@model IndexModel
...
Name: @HttpContext.Session.GetString(IndexModel.SessionKeyName)
Contoh berikut menunjukkan cara mengatur dan mendapatkan bilangan bulat dan string:
public class IndexModel : PageModel
{
public const string SessionKeyName = "_Name";
public const string SessionKeyAge = "_Age";
private readonly ILogger<IndexModel> _logger;
public IndexModel(ILogger<IndexModel> logger)
{
_logger = logger;
}
public void OnGet()
{
if (string.IsNullOrEmpty(HttpContext.Session.GetString(SessionKeyName)))
{
HttpContext.Session.SetString(SessionKeyName, "The Doctor");
HttpContext.Session.SetInt32(SessionKeyAge, 73);
}
var name = HttpContext.Session.GetString(SessionKeyName);
var age = HttpContext.Session.GetInt32(SessionKeyAge).ToString();
_logger.LogInformation("Session Name: {Name}", name);
_logger.LogInformation("Session Age: {Age}", age);
}
}
Markup berikut menampilkan nilai sesi pada Razor Halaman:
@page
@model PrivacyModel
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<div class="text-center">
<p><b>Name:</b> @HttpContext.Session.GetString("_Name");<b>Age:
</b> @HttpContext.Session.GetInt32("_Age").ToString()</p>
</div>
Semua data sesi harus diserialisasikan untuk mengaktifkan skenario cache terdistribusi, bahkan saat menggunakan cache dalam memori. Serializer string dan bilangan bulat disediakan oleh metode ekstensi .ISession Jenis kompleks harus diserialisasikan oleh pengguna menggunakan mekanisme lain, seperti JSON.
Gunakan kode sampel berikut untuk menserialisasikan objek:
public static class SessionExtensions
{
public static void Set<T>(this ISession session, string key, T value)
{
session.SetString(key, JsonSerializer.Serialize(value));
}
public static T? Get<T>(this ISession session, string key)
{
var value = session.GetString(key);
return value == null ? default : JsonSerializer.Deserialize<T>(value);
}
}
Contoh berikut menunjukkan cara mengatur dan mendapatkan objek yang dapat diserialisasikan dengan SessionExtensions
kelas :
using Microsoft.AspNetCore.Mvc.RazorPages;
using Web.Extensions; // SessionExtensions
namespace SessionSample.Pages
{
public class Index6Model : PageModel
{
const string SessionKeyTime = "_Time";
public string? SessionInfo_SessionTime { get; private set; }
private readonly ILogger<Index6Model> _logger;
public Index6Model(ILogger<Index6Model> logger)
{
_logger = logger;
}
public void OnGet()
{
var currentTime = DateTime.Now;
// Requires SessionExtensions from sample.
if (HttpContext.Session.Get<DateTime>(SessionKeyTime) == default)
{
HttpContext.Session.Set<DateTime>(SessionKeyTime, currentTime);
}
_logger.LogInformation("Current Time: {Time}", currentTime);
_logger.LogInformation("Session Time: {Time}",
HttpContext.Session.Get<DateTime>(SessionKeyTime));
}
}
}
Peringatan
Menyimpan objek langsung dalam sesi harus digunakan dengan hati-hati, karena ada banyak masalah yang dapat terjadi dengan objek berseri. Untuk informasi selengkapnya, lihat Sesi harus diizinkan untuk menyimpan objek (dotnet/aspnetcore #18159).
TempData
ASP.NET Core mengekspos Razor Halaman TempData atau Pengontrol TempData. Properti ini menyimpan data hingga dibaca dalam permintaan lain. Metode Keep(String) dan Peek(string) dapat digunakan untuk memeriksa data tanpa penghapusan di akhir permintaan. Pertahankan tandai semua item dalam kamus untuk retensi. TempData
sedang:
- Berguna untuk pengalihan saat data diperlukan untuk lebih dari satu permintaan.
- Diimplementasikan oleh
TempData
penyedia menggunakan cookie atau status sesi.
Sampel TempData
Pertimbangkan halaman berikut yang membuat pelanggan:
public class CreateModel : PageModel
{
private readonly RazorPagesContactsContext _context;
public CreateModel(RazorPagesContactsContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[TempData]
public string Message { get; set; }
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Customer.Add(Customer);
await _context.SaveChangesAsync();
Message = $"Customer {Customer.Name} added";
return RedirectToPage("./IndexPeek");
}
}
Halaman berikut menampilkan TempData["Message"]
:
@page
@model IndexModel
<h1>Peek Contacts</h1>
@{
if (TempData.Peek("Message") != null)
{
<h3>Message: @TempData.Peek("Message")</h3>
}
}
@*Content removed for brevity.*@
Dalam markup sebelumnya, di akhir permintaan, TempData["Message"]
tidak dihapus karena Peek
digunakan. Menyegarkan halaman menampilkan konten TempData["Message"]
.
Markup berikut mirip dengan kode sebelumnya, tetapi menggunakan Keep
untuk mempertahankan data di akhir permintaan:
@page
@model IndexModel
<h1>Contacts Keep</h1>
@{
if (TempData["Message"] != null)
{
<h3>Message: @TempData["Message"]</h3>
}
TempData.Keep("Message");
}
@*Content removed for brevity.*@
Menavigasi antara halaman IndexPeek dan IndexKeep tidak akan menghapus TempData["Message"]
.
Kode berikut menampilkan TempData["Message"]
, tetapi di akhir permintaan, TempData["Message"]
dihapus:
@page
@model IndexModel
<h1>Index no Keep or Peek</h1>
@{
if (TempData["Message"] != null)
{
<h3>Message: @TempData["Message"]</h3>
}
}
@*Content removed for brevity.*@
Penyedia TempData
Penyedia cookieTempData berbasis digunakan secara default untuk menyimpan TempData dalam cookie.
Data cookie dienkripsi menggunakan IDataProtector, dikodekan dengan Base64UrlTextEncoder, lalu dipotong. Ukuran maksimum cookie kurang dari 4096 byte karena enkripsi dan potongan. Data cookie tidak dikompresi karena mengompresi data terenkripsi dapat menyebabkan masalah keamanan seperti CRIME serangan dan BREACH . Untuk informasi selengkapnya tentang cookiepenyedia TempData berbasis, lihat CookieTempDataProvider.
Pilih penyedia TempData
Memilih penyedia TempData melibatkan beberapa pertimbangan, seperti:
- Apakah aplikasi sudah menggunakan status sesi? Jika demikian, menggunakan status sesi penyedia TempData tidak memiliki biaya tambahan untuk aplikasi di luar ukuran data.
- Apakah aplikasi menggunakan TempData hanya hemat untuk jumlah data yang relatif kecil, hingga 500 byte? Jika demikian, cookie penyedia TempData menambahkan biaya kecil ke setiap permintaan yang membawa TempData. Jika tidak, penyedia TempData status sesi dapat bermanfaat untuk menghindari round-tripping sejumlah besar data di setiap permintaan hingga TempData dikonsumsi.
- Apakah aplikasi berjalan di farm server di beberapa server? Jika demikian, tidak ada konfigurasi tambahan yang diperlukan untuk menggunakan cookie penyedia TempData di luar Perlindungan Data. Untuk informasi selengkapnya, lihat Gambaran Umum Perlindungan Data Inti ASP.NET dan Penyedia penyimpanan Kunci.
Sebagian besar klien web seperti browser web memberlakukan batasan pada ukuran maksimum masing-masing cookie dan jumlah total cookie. Saat menggunakan cookie penyedia TempData, verifikasi aplikasi tidak akan melebihi batas ini. Pertimbangkan ukuran total data. Memperhitungkan cookie peningkatan ukuran karena enkripsi dan potongan.
Mengonfigurasi penyedia TempData
Penyedia cookieTempData berbasis diaktifkan secara default.
Untuk mengaktifkan penyedia TempData berbasis sesi, gunakan AddSessionStateTempDataProvider metode ekstensi. Hanya satu panggilan ke AddSessionStateTempDataProvider
yang diperlukan:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages()
.AddSessionStateTempDataProvider();
builder.Services.AddControllersWithViews()
.AddSessionStateTempDataProvider();
builder.Services.AddSession();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseSession();
app.MapRazorPages();
app.MapDefaultControllerRoute();
app.Run();
String kueri
Sejumlah data terbatas dapat diteruskan dari satu permintaan ke permintaan lain dengan menambahkannya ke string kueri permintaan baru. Ini berguna untuk menangkap status dengan cara yang persisten yang memungkinkan tautan dengan status tersemat dibagikan melalui email atau jejaring sosial. Karena string kueri URL bersifat publik, jangan pernah menggunakan string kueri untuk data sensitif.
Selain berbagi yang tidak diinginkan, termasuk data dalam string kueri dapat mengekspos aplikasi ke serangan Pemalsuan Permintaan Lintas Situs (CSRF ). Setiap status sesi yang dipertahankan harus melindungi dari serangan CSRF. Untuk informasi selengkapnya, lihat Mencegah serangan Pemalsuan Permintaan Antar Situs (XSRF/CSRF) di ASP.NET Core.
Bidang tersembunyi
Data dapat disimpan dalam bidang formulir tersembunyi dan diposting kembali pada permintaan berikutnya. Ini umum dalam bentuk multi-halaman. Karena klien berpotensi mengubah data, aplikasi harus selalu memvalidasi ulang data yang disimpan di bidang tersembunyi.
HttpContext.Items
Koleksi HttpContext.Items digunakan untuk menyimpan data saat memproses satu permintaan. Konten koleksi dibuang setelah permintaan diproses. Koleksi Items
sering digunakan untuk memungkinkan komponen atau middleware berkomunikasi ketika mereka beroperasi di titik waktu yang berbeda selama permintaan dan tidak memiliki cara langsung untuk meneruskan parameter.
Dalam contoh berikut, middleware menambahkan isVerified
ke Items
koleksi:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
ILogger logger = app.Logger;
app.Use(async (context, next) =>
{
// context.Items["isVerified"] is null
logger.LogInformation($"Before setting: Verified: {context.Items["isVerified"]}");
context.Items["isVerified"] = true;
await next.Invoke();
});
app.Use(async (context, next) =>
{
// context.Items["isVerified"] is true
logger.LogInformation($"Next: Verified: {context.Items["isVerified"]}");
await next.Invoke();
});
app.MapGet("/", async context =>
{
await context.Response.WriteAsync($"Verified: {context.Items["isVerified"]}");
});
app.Run();
Untuk middleware yang hanya digunakan dalam satu aplikasi, tidak mungkin menggunakan kunci tetap akan menyebabkan tabrakan string
kunci. Namun, untuk menghindari kemungkinan tabrakan kunci sama sekali, dapat object
digunakan sebagai kunci item. Pendekatan ini sangat berguna untuk middleware yang dibagikan antara aplikasi dan juga memiliki keuntungan menghilangkan penggunaan string kunci dalam kode. Contoh berikut menunjukkan cara menggunakan kunci yang object
ditentukan dalam kelas middleware:
public class HttpContextItemsMiddleware
{
private readonly RequestDelegate _next;
public static readonly object HttpContextItemsMiddlewareKey = new();
public HttpContextItemsMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext)
{
httpContext.Items[HttpContextItemsMiddlewareKey] = "K-9";
await _next(httpContext);
}
}
public static class HttpContextItemsMiddlewareExtensions
{
public static IApplicationBuilder
UseHttpContextItemsMiddleware(this IApplicationBuilder app)
{
return app.UseMiddleware<HttpContextItemsMiddleware>();
}
}
Kode lain dapat mengakses nilai yang disimpan dalam HttpContext.Items
menggunakan kunci yang diekspos oleh kelas middleware:
public class Index2Model : PageModel
{
private readonly ILogger<Index2Model> _logger;
public Index2Model(ILogger<Index2Model> logger)
{
_logger = logger;
}
public void OnGet()
{
HttpContext.Items
.TryGetValue(HttpContextItemsMiddleware.HttpContextItemsMiddlewareKey,
out var middlewareSetValue);
_logger.LogInformation("Middleware value {MV}",
middlewareSetValue?.ToString() ?? "Middleware value not set!");
}
}
Cache
Penembolokan adalah cara yang efisien untuk menyimpan dan mengambil data. Aplikasi ini dapat mengontrol masa pakai item yang di-cache. Untuk informasi selengkapnya, lihat Penembolokan respons di ASP.NET Core.
Data yang di-cache tidak terkait dengan permintaan, pengguna, atau sesi tertentu. Jangan cache data khusus pengguna yang dapat diambil oleh permintaan pengguna lain.
Untuk menyimpan data luas aplikasi, lihat Cache dalam memori di ASP.NET Core.
Memeriksa status sesi
ISession.IsAvailable dimaksudkan untuk memeriksa kegagalan sementara. Memanggil IsAvailable
sebelum middleware sesi berjalan melempar .InvalidOperationException
Pustaka yang perlu menguji ketersediaan sesi dapat menggunakan HttpContext.Features.Get<ISessionFeature>()?.Session != null
.
Kesalahan umum
"Tidak dapat mengatasi layanan untuk jenis 'Microsoft.Extensions.Caching.Distributed.IDistributedCache' saat mencoba mengaktifkan 'Microsoft.AspNetCore.Session.DistributedSessionStore'."
Ini biasanya disebabkan oleh gagal mengonfigurasi setidaknya satu
IDistributedCache
implementasi. Untuk informasi selengkapnya, lihat Penembolokan terdistribusi di ASP.NET Core dan Cache dalam memori di ASP.NET Core.
Jika middleware sesi gagal mempertahankan sesi:
- Middleware mencatat pengecualian dan permintaan berlanjut secara normal.
- Hal ini menyebabkan perilaku yang tidak dapat diprediksi.
Middleware sesi dapat gagal mempertahankan sesi jika penyimpanan backing tidak tersedia. Misalnya, pengguna menyimpan kelir belanja dalam sesi. Pengguna menambahkan item ke ke troli tetapi penerapan gagal. Aplikasi tidak tahu tentang kegagalan sehingga melaporkan kepada pengguna bahwa item ditambahkan ke kelir mereka, yang tidak benar.
Pendekatan yang disarankan untuk memeriksa kesalahan adalah dengan memanggil await feature.Session.CommitAsync
ketika aplikasi selesai menulis ke sesi. CommitAsync melempar pengecualian jika penyimpanan cadangan tidak tersedia. Jika CommitAsync
gagal, aplikasi dapat memproses pengecualian. LoadAsync melemparkan dalam kondisi yang sama ketika penyimpanan data tidak tersedia.
Sumber Daya Tambahan:
Oleh Rick Anderson, Kirk Larkin, dan Diana LaRose
HTTP adalah protokol stateless. Secara default, permintaan HTTP adalah pesan independen yang tidak mempertahankan nilai pengguna. Artikel ini menjelaskan beberapa pendekatan untuk mempertahankan data pengguna antar permintaan.
Melihat atau mengunduh kode sampel (cara mengunduh)
Manajemen Status
Status dapat disimpan menggunakan beberapa pendekatan. Setiap pendekatan dijelaskan nanti dalam artikel ini.
Pendekatan penyimpanan | Mekanisme penyimpanan |
---|---|
Cookie | Cookie HTTP. Dapat mencakup data yang disimpan menggunakan kode aplikasi sisi server. |
Status sesi | Cookie HTTP dan kode aplikasi sisi server |
TempData | Cookie HTTP atau status sesi |
String kueri | String kueri HTTP |
Bidang tersembunyi | Bidang formulir HTTP |
HttpContext.Items | Kode aplikasi sisi server |
Cache | Kode aplikasi sisi server |
SignalR/Blazor Server dan manajemen status berbasis konteks HTTP
SignalR aplikasi tidak boleh menggunakan status sesi dan pendekatan manajemen status lainnya yang mengandalkan konteks HTTP yang stabil untuk menyimpan informasi. SignalR aplikasi dapat menyimpan status per koneksi di Context.Items
hub. Untuk informasi selengkapnya dan pendekatan manajemen status alternatif untuk Blazor Server aplikasi, lihat manajemen status ASP.NET CoreBlazor.
Cookie
Cookie menyimpan data di seluruh permintaan. Karena cookie dikirim dengan setiap permintaan, ukurannya harus dijaga seminimal mungkin. Idealnya, hanya pengidentifikasi yang harus disimpan dalam dengan data yang cookie disimpan oleh aplikasi. Sebagian besar browser membatasi cookie ukuran hingga 4096 byte. Hanya sejumlah cookie terbatas yang tersedia untuk setiap domain.
Karena cookie dapat diubah, cookie harus divalidasi oleh aplikasi. Cookie dapat dihapus oleh pengguna dan kedaluwarsa pada klien. Namun, cookie umumnya merupakan bentuk persistensi data yang paling tahan lama pada klien.
Cookie sering digunakan untuk personalisasi, di mana konten disesuaikan untuk pengguna yang dikenal. Pengguna hanya diidentifikasi dan tidak diautentikasi dalam banyak kasus. cookie dapat menyimpan nama pengguna, nama akun, atau ID pengguna unik seperti GUID. cookie dapat digunakan untuk mengakses pengaturan yang dipersonalisasi pengguna, seperti warna latar belakang situs web pilihan mereka.
Lihat Peraturan Perlindungan Data Umum Uni Eropa (GDPR) saat mengeluarkan cookie dan berurusan dengan privacy masalah. Untuk informasi selengkapnya, lihat Dukungan Peraturan Perlindungan Data Umum (GDPR) di ASP.NET Core.
Status sesi
Status sesi adalah skenario ASP.NET Core untuk penyimpanan data pengguna saat pengguna menelusuri aplikasi web. Status sesi menggunakan penyimpanan yang dikelola oleh aplikasi untuk mempertahankan data di seluruh permintaan dari klien. Data sesi didukung oleh cache dan dianggap sebagai data ephemeral. Situs harus terus berfungsi tanpa data sesi. Data aplikasi penting harus disimpan dalam database pengguna dan di-cache dalam sesi hanya sebagai pengoptimalan performa.
Sesi tidak didukung di SignalR aplikasi karena SignalR Hub dapat menjalankan independen dari konteks HTTP. Misalnya, ini dapat terjadi ketika permintaan polling panjang ditahan terbuka oleh hub di luar masa pakai konteks HTTP permintaan.
ASP.NET Core mempertahankan status sesi dengan memberikan cookie kepada klien yang berisi ID sesi. cookie ID sesi:
- Dikirim ke aplikasi dengan setiap permintaan.
- Digunakan oleh aplikasi untuk mengambil data sesi.
Status sesi menunjukkan perilaku berikut:
- Sesi cookie ini khusus untuk browser. Sesi tidak dibagikan di seluruh browser.
- Cookie sesi dihapus ketika sesi browser berakhir.
- cookie Jika diterima untuk sesi yang kedaluwarsa, sesi baru dibuat yang menggunakan sesi cookieyang sama .
- Sesi kosong tidak dipertahankan. Sesi harus memiliki setidaknya satu nilai yang diatur untuk mempertahankan sesi di seluruh permintaan. Saat sesi tidak dipertahankan, ID sesi baru dibuat untuk setiap permintaan baru.
- Aplikasi mempertahankan sesi untuk waktu yang terbatas setelah permintaan terakhir. Aplikasi mengatur batas waktu sesi atau menggunakan nilai default 20 menit. Status sesi sangat ideal untuk menyimpan data pengguna:
- Itu khusus untuk sesi tertentu.
- Jika data tidak memerlukan penyimpanan permanen di seluruh sesi.
- Data sesi dihapus baik ketika implementasi dipanggil ISession.Clear atau ketika sesi kedaluwarsa.
- Tidak ada mekanisme default untuk menginformasikan kode aplikasi bahwa browser klien telah ditutup atau ketika sesi cookie dihapus atau kedaluwarsa pada klien.
- Cookie status sesi tidak ditandai penting secara default. Status sesi tidak berfungsi kecuali pelacakan diizinkan oleh pengunjung situs. Untuk informasi selengkapnya, lihat Dukungan Peraturan Perlindungan Data Umum (GDPR) di ASP.NET Core.
Peringatan
Jangan simpan data sensitif dalam status sesi. Pengguna mungkin tidak menutup browser dan menghapus sesi cookie. Beberapa browser mempertahankan cookie sesi yang valid di seluruh jendela browser. Sesi mungkin tidak dibatasi untuk satu pengguna. Pengguna berikutnya mungkin terus menelusuri aplikasi dengan sesi cookieyang sama.
Penyedia cache dalam memori menyimpan data sesi dalam memori server tempat aplikasi berada. Dalam skenario farm server:
- Gunakan sesi lekat untuk mengikat setiap sesi ke instans aplikasi tertentu di server individual. Azure App Service menggunakan Perutean Permintaan Aplikasi (ARR) untuk menerapkan sesi lekat secara default. Namun, sesi lengket dapat memengaruhi skalabilitas dan mempersulit pembaruan aplikasi web. Pendekatan yang lebih baik adalah menggunakan cache terdistribusi Redis atau SQL Server, yang tidak memerlukan sesi lengket. Untuk informasi selengkapnya, lihat Penembolokan terdistribusi di ASP.NET Core.
- Sesi cookie dienkripsi melalui IDataProtector. Perlindungan Data harus dikonfigurasi dengan benar untuk membaca cookie sesi pada setiap komputer. Untuk informasi selengkapnya, lihat Gambaran Umum Perlindungan Data Inti ASP.NET dan Penyedia penyimpanan Kunci.
Mengonfigurasi status sesi
Paket Microsoft.AspNetCore.Session :
- Disertakan secara implisit oleh kerangka kerja.
- Menyediakan middleware untuk mengelola status sesi.
Untuk mengaktifkan middleware sesi, Startup
harus berisi:
- IDistributedCache Salah satu cache memori. Implementasi
IDistributedCache
digunakan sebagai penyimpanan backing untuk sesi. Untuk informasi selengkapnya, lihat Penembolokan terdistribusi di ASP.NET Core. - Panggilan ke AddSession dalam
ConfigureServices
. - Panggilan ke UseSession dalam
Configure
.
Kode berikut menunjukkan cara menyiapkan penyedia sesi dalam memori dengan implementasi dalam memori default dari IDistributedCache
:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
services.AddControllersWithViews();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapRazorPages();
});
}
}
Kode sebelumnya menetapkan batas waktu yang singkat untuk menyederhanakan pengujian.
Urutan middleware penting. Hubungi UseSession
setelah UseRouting
dan sebelum UseEndpoints
. Lihat Pemesanan Middleware.
HttpContext.Session tersedia setelah status sesi dikonfigurasi.
HttpContext.Session
tidak dapat diakses sebelumnya UseSession
telah dipanggil.
Sesi baru dengan sesi cookie baru tidak dapat dibuat setelah aplikasi mulai menulis ke aliran respons. Pengecualian direkam di log server web dan tidak ditampilkan di browser.
Memuat status sesi secara asinkron
Penyedia sesi default di ASP.NET Core memuat rekaman sesi dari penyimpanan pendukung yang mendasar IDistributedCache secara asinkron hanya jika ISession.LoadAsync metode secara eksplisit dipanggil sebelum TryGetValuemetode , , Setatau Remove . Jika LoadAsync
tidak dipanggil terlebih dahulu, rekaman sesi yang mendasar dimuat secara sinkron, yang dapat dikenakan penalti performa dalam skala besar.
Agar aplikasi menerapkan pola ini, bungkus DistributedSessionStore implementasi dan DistributedSession dengan versi yang melemparkan pengecualian jika LoadAsync
metode tidak dipanggil sebelum TryGetValue
, , Set
atau Remove
. Daftarkan versi yang dibungkus dalam kontainer layanan.
Opsi sesi
Untuk mengambil alih default sesi, gunakan SessionOptions.
Opsi | Deskripsi |
---|---|
Cookie | Menentukan pengaturan yang digunakan untuk membuat cookie. Name default ke SessionDefaults.CookieName (.AspNetCore.Session ). Path default ke SessionDefaults.CookiePath (/ ). SameSite default ke SameSiteMode.Lax (1 ). HttpOnly defaultnya adalah true . IsEssential defaultnya adalah false . |
IdleTimeout | menunjukkan IdleTimeout berapa lama sesi dapat diam sebelum kontennya ditinggalkan. Setiap akses sesi mengatur ulang batas waktu. Pengaturan ini hanya berlaku untuk konten sesi, bukan cookie. Defaultnya adalah 20 menit. |
IOTimeout | Jumlah waktu maksimum yang diizinkan untuk memuat sesi dari penyimpanan atau untuk menerapkannya kembali ke penyimpanan. Pengaturan ini mungkin hanya berlaku untuk operasi asinkron. Batas waktu ini dapat dinonaktifkan menggunakan InfiniteTimeSpan. Defaultnya adalah 1 menit. |
Sesi menggunakan cookie untuk melacak dan mengidentifikasi permintaan dari satu browser. Secara default, ini cookie bernama .AspNetCore.Session
, dan menggunakan jalur /
. cookie Karena default tidak menentukan domain, domain tidak tersedia untuk skrip sisi klien di halaman (karena HttpOnly default ke true
).
Untuk mengambil alih cookie default sesi, gunakan SessionOptions:
public void ConfigureServices(IServiceCollection services)
{
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.Cookie.Name = ".AdventureWorks.Session";
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.IsEssential = true;
});
services.AddControllersWithViews();
services.AddRazorPages();
}
Aplikasi ini menggunakan IdleTimeout properti untuk menentukan berapa lama sesi dapat menganggur sebelum kontennya di cache server ditinggalkan. Properti ini tidak bergantung pada kedaluwarsa cookie . Setiap permintaan yang melewati Middleware Sesi mengatur ulang batas waktu.
Status sesi tidak terkunci. Jika dua permintaan secara bersamaan mencoba memodifikasi konten sesi, permintaan terakhir akan mengambil alih yang pertama. Session
diimplementasikan sebagai sesi yang koheren, yang berarti bahwa semua konten disimpan bersama-sama. Ketika dua permintaan berusaha mengubah nilai sesi yang berbeda, permintaan terakhir dapat mengambil alih perubahan sesi yang dibuat oleh yang pertama.
Mengatur dan mendapatkan nilai Sesi
Status sesi diakses dari Razor kelas Pages PageModel atau kelas MVC Controller dengan HttpContext.Session. Properti ini adalah ISession implementasi.
Implementasi ini ISession
menyediakan beberapa metode ekstensi untuk mengatur dan mengambil nilai bilangan bulat dan string. Metode ekstensi berada di Microsoft.AspNetCore.Http namespace layanan.
ISession
metode ekstensi:
- Get(ISession, String)
- GetInt32(ISession, String)
- GetString(ISession, String)
- SetInt32(ISession, String, Int32)
- SetString(ISession, String, String)
Contoh berikut mengambil nilai sesi untuk IndexModel.SessionKeyName
kunci (_Name
di aplikasi sampel) di Razor halaman Halaman:
@page
@using Microsoft.AspNetCore.Http
@model IndexModel
...
Name: @HttpContext.Session.GetString(IndexModel.SessionKeyName)
Contoh berikut menunjukkan cara mengatur dan mendapatkan bilangan bulat dan string:
public class IndexModel : PageModel
{
public const string SessionKeyName = "_Name";
public const string SessionKeyAge = "_Age";
const string SessionKeyTime = "_Time";
public string SessionInfo_Name { get; private set; }
public string SessionInfo_Age { get; private set; }
public string SessionInfo_CurrentTime { get; private set; }
public string SessionInfo_SessionTime { get; private set; }
public string SessionInfo_MiddlewareValue { get; private set; }
public void OnGet()
{
// Requires: using Microsoft.AspNetCore.Http;
if (string.IsNullOrEmpty(HttpContext.Session.GetString(SessionKeyName)))
{
HttpContext.Session.SetString(SessionKeyName, "The Doctor");
HttpContext.Session.SetInt32(SessionKeyAge, 773);
}
var name = HttpContext.Session.GetString(SessionKeyName);
var age = HttpContext.Session.GetInt32(SessionKeyAge);
Semua data sesi harus diserialisasikan untuk mengaktifkan skenario cache terdistribusi, bahkan saat menggunakan cache dalam memori. Serializer string dan bilangan bulat disediakan oleh metode ekstensi .ISession Jenis kompleks harus diserialisasikan oleh pengguna menggunakan mekanisme lain, seperti JSON.
Gunakan kode sampel berikut untuk menserialisasikan objek:
public static class SessionExtensions
{
public static void Set<T>(this ISession session, string key, T value)
{
session.SetString(key, JsonSerializer.Serialize(value));
}
public static T Get<T>(this ISession session, string key)
{
var value = session.GetString(key);
return value == null ? default : JsonSerializer.Deserialize<T>(value);
}
}
Contoh berikut menunjukkan cara mengatur dan mendapatkan objek yang dapat diserialisasikan dengan SessionExtensions
kelas :
// Requires SessionExtensions from sample download.
if (HttpContext.Session.Get<DateTime>(SessionKeyTime) == default)
{
HttpContext.Session.Set<DateTime>(SessionKeyTime, currentTime);
}
TempData
ASP.NET Core mengekspos Razor Halaman TempData atau Pengontrol TempData. Properti ini menyimpan data hingga dibaca dalam permintaan lain. Metode Keep(String) dan Peek(string) dapat digunakan untuk memeriksa data tanpa penghapusan di akhir permintaan. Pertahankan tandai semua item dalam kamus untuk retensi. TempData
sedang:
- Berguna untuk pengalihan saat data diperlukan untuk lebih dari satu permintaan.
- Diimplementasikan oleh
TempData
penyedia menggunakan cookie atau status sesi.
Sampel TempData
Pertimbangkan halaman berikut yang membuat pelanggan:
public class CreateModel : PageModel
{
private readonly RazorPagesContactsContext _context;
public CreateModel(RazorPagesContactsContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[TempData]
public string Message { get; set; }
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Customer.Add(Customer);
await _context.SaveChangesAsync();
Message = $"Customer {Customer.Name} added";
return RedirectToPage("./IndexPeek");
}
}
Halaman berikut menampilkan TempData["Message"]
:
@page
@model IndexModel
<h1>Peek Contacts</h1>
@{
if (TempData.Peek("Message") != null)
{
<h3>Message: @TempData.Peek("Message")</h3>
}
}
@*Content removed for brevity.*@
Dalam markup sebelumnya, di akhir permintaan, TempData["Message"]
tidak dihapus karena Peek
digunakan. Menyegarkan halaman menampilkan konten TempData["Message"]
.
Markup berikut mirip dengan kode sebelumnya, tetapi menggunakan Keep
untuk mempertahankan data di akhir permintaan:
@page
@model IndexModel
<h1>Contacts Keep</h1>
@{
if (TempData["Message"] != null)
{
<h3>Message: @TempData["Message"]</h3>
}
TempData.Keep("Message");
}
@*Content removed for brevity.*@
Menavigasi antara halaman IndexPeek dan IndexKeep tidak akan menghapus TempData["Message"]
.
Kode berikut menampilkan TempData["Message"]
, tetapi di akhir permintaan, TempData["Message"]
dihapus:
@page
@model IndexModel
<h1>Index no Keep or Peek</h1>
@{
if (TempData["Message"] != null)
{
<h3>Message: @TempData["Message"]</h3>
}
}
@*Content removed for brevity.*@
Penyedia TempData
Penyedia cookieTempData berbasis digunakan secara default untuk menyimpan TempData dalam cookie.
Data cookie dienkripsi menggunakan IDataProtector, dikodekan dengan Base64UrlTextEncoder, lalu dipotong. Ukuran maksimum cookie kurang dari 4096 byte karena enkripsi dan potongan. Data cookie tidak dikompresi karena mengompresi data terenkripsi dapat menyebabkan masalah keamanan seperti CRIME serangan dan BREACH . Untuk informasi selengkapnya tentang cookiepenyedia TempData berbasis, lihat CookieTempDataProvider.
Pilih penyedia TempData
Memilih penyedia TempData melibatkan beberapa pertimbangan, seperti:
- Apakah aplikasi sudah menggunakan status sesi? Jika demikian, menggunakan status sesi penyedia TempData tidak memiliki biaya tambahan untuk aplikasi di luar ukuran data.
- Apakah aplikasi menggunakan TempData hanya hemat untuk jumlah data yang relatif kecil, hingga 500 byte? Jika demikian, cookie penyedia TempData menambahkan biaya kecil ke setiap permintaan yang membawa TempData. Jika tidak, penyedia TempData status sesi dapat bermanfaat untuk menghindari round-tripping sejumlah besar data di setiap permintaan hingga TempData dikonsumsi.
- Apakah aplikasi berjalan di farm server di beberapa server? Jika demikian, tidak ada konfigurasi tambahan yang diperlukan untuk menggunakan cookie penyedia TempData di luar Perlindungan Data (lihat ASP.NET Gambaran Umum Perlindungan Data Inti dan Penyedia penyimpanan kunci).
Sebagian besar klien web seperti browser web memberlakukan batasan pada ukuran maksimum masing-masing cookie dan jumlah total cookie. Saat menggunakan cookie penyedia TempData, verifikasi aplikasi tidak akan melebihi batas ini. Pertimbangkan ukuran total data. Memperhitungkan cookie peningkatan ukuran karena enkripsi dan potongan.
Mengonfigurasi penyedia TempData
Penyedia cookieTempData berbasis diaktifkan secara default.
Untuk mengaktifkan penyedia TempData berbasis sesi, gunakan AddSessionStateTempDataProvider metode ekstensi. Hanya satu panggilan ke AddSessionStateTempDataProvider
yang diperlukan:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews()
.AddSessionStateTempDataProvider();
services.AddRazorPages()
.AddSessionStateTempDataProvider();
services.AddSession();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapRazorPages();
});
}
String kueri
Sejumlah data terbatas dapat diteruskan dari satu permintaan ke permintaan lain dengan menambahkannya ke string kueri permintaan baru. Ini berguna untuk menangkap status dengan cara yang persisten yang memungkinkan tautan dengan status tersemat dibagikan melalui email atau jejaring sosial. Karena string kueri URL bersifat publik, jangan pernah menggunakan string kueri untuk data sensitif.
Selain berbagi yang tidak diinginkan, termasuk data dalam string kueri dapat mengekspos aplikasi ke serangan Pemalsuan Permintaan Lintas Situs (CSRF ). Setiap status sesi yang dipertahankan harus melindungi dari serangan CSRF. Untuk informasi selengkapnya, lihat Mencegah serangan Pemalsuan Permintaan Antar Situs (XSRF/CSRF) di ASP.NET Core.
Bidang tersembunyi
Data dapat disimpan dalam bidang formulir tersembunyi dan diposting kembali pada permintaan berikutnya. Ini umum dalam bentuk multi-halaman. Karena klien berpotensi mengubah data, aplikasi harus selalu memvalidasi ulang data yang disimpan di bidang tersembunyi.
HttpContext.Items
Koleksi HttpContext.Items digunakan untuk menyimpan data saat memproses satu permintaan. Konten koleksi dibuang setelah permintaan diproses. Koleksi Items
sering digunakan untuk memungkinkan komponen atau middleware berkomunikasi ketika mereka beroperasi di titik waktu yang berbeda selama permintaan dan tidak memiliki cara langsung untuk meneruskan parameter.
Dalam contoh berikut, middleware menambahkan isVerified
ke Items
koleksi:
public void Configure(IApplicationBuilder app, ILogger<Startup> logger)
{
app.UseRouting();
app.Use(async (context, next) =>
{
logger.LogInformation($"Before setting: Verified: {context.Items["isVerified"]}");
context.Items["isVerified"] = true;
await next.Invoke();
});
app.Use(async (context, next) =>
{
logger.LogInformation($"Next: Verified: {context.Items["isVerified"]}");
await next.Invoke();
});
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync($"Verified: {context.Items["isVerified"]}");
});
});
}
Untuk middleware yang hanya digunakan dalam satu aplikasi, kunci tetap string
dapat diterima. Middleware yang dibagikan antar aplikasi harus menggunakan kunci objek unik untuk menghindari tabrakan kunci. Contoh berikut menunjukkan cara menggunakan kunci objek unik yang ditentukan dalam kelas middleware:
public class HttpContextItemsMiddleware
{
private readonly RequestDelegate _next;
public static readonly object HttpContextItemsMiddlewareKey = new Object();
public HttpContextItemsMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext)
{
httpContext.Items[HttpContextItemsMiddlewareKey] = "K-9";
await _next(httpContext);
}
}
public static class HttpContextItemsMiddlewareExtensions
{
public static IApplicationBuilder
UseHttpContextItemsMiddleware(this IApplicationBuilder app)
{
return app.UseMiddleware<HttpContextItemsMiddleware>();
}
}
Kode lain dapat mengakses nilai yang disimpan dalam HttpContext.Items
menggunakan kunci yang diekspos oleh kelas middleware:
HttpContext.Items
.TryGetValue(HttpContextItemsMiddleware.HttpContextItemsMiddlewareKey,
out var middlewareSetValue);
SessionInfo_MiddlewareValue =
middlewareSetValue?.ToString() ?? "Middleware value not set!";
Pendekatan ini juga memiliki keuntungan menghilangkan penggunaan string kunci dalam kode.
Cache
Penembolokan adalah cara yang efisien untuk menyimpan dan mengambil data. Aplikasi ini dapat mengontrol masa pakai item yang di-cache. Untuk informasi selengkapnya, lihat Penembolokan respons di ASP.NET Core.
Data yang di-cache tidak terkait dengan permintaan, pengguna, atau sesi tertentu. Jangan cache data khusus pengguna yang dapat diambil oleh permintaan pengguna lain.
Untuk menyimpan data luas aplikasi, lihat Cache dalam memori di ASP.NET Core.
Kesalahan umum
"Tidak dapat mengatasi layanan untuk jenis 'Microsoft.Extensions.Caching.Distributed.IDistributedCache' saat mencoba mengaktifkan 'Microsoft.AspNetCore.Session.DistributedSessionStore'."
Ini biasanya disebabkan oleh gagal mengonfigurasi setidaknya satu
IDistributedCache
implementasi. Untuk informasi selengkapnya, lihat Penembolokan terdistribusi di ASP.NET Core dan Cache dalam memori di ASP.NET Core.
Jika middleware sesi gagal mempertahankan sesi:
- Middleware mencatat pengecualian dan permintaan berlanjut secara normal.
- Hal ini menyebabkan perilaku yang tidak dapat diprediksi.
Middleware sesi dapat gagal mempertahankan sesi jika penyimpanan backing tidak tersedia. Misalnya, pengguna menyimpan kelir belanja dalam sesi. Pengguna menambahkan item ke ke troli tetapi penerapan gagal. Aplikasi tidak tahu tentang kegagalan sehingga melaporkan kepada pengguna bahwa item ditambahkan ke kelir mereka, yang tidak benar.
Pendekatan yang disarankan untuk memeriksa kesalahan adalah dengan memanggil await feature.Session.CommitAsync
ketika aplikasi selesai menulis ke sesi. CommitAsync melempar pengecualian jika penyimpanan cadangan tidak tersedia. Jika CommitAsync
gagal, aplikasi dapat memproses pengecualian. LoadAsync melemparkan dalam kondisi yang sama ketika penyimpanan data tidak tersedia.
Sumber Daya Tambahan:
ASP.NET Core