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.
Manajemen Status
Status dapat disimpan menggunakan beberapa pendekatan. Setiap pendekatan dijelaskan nanti dalam topik ini.
| Pendekatan penyimpanan | Mekanisme penyimpanan |
|---|---|
| CookieS | HTTP cookies. Dapat mencakup data yang disimpan menggunakan kode aplikasi sisi server. |
| Status sesi | HTTP cookies dan kode aplikasi sisi server |
| TempData | STATUS HTTP cookieatau sesi |
| String kueri | String kueri HTTP |
| Bidang tersembunyi | Bidang formulir HTTP |
| HttpContext.Items | Kode aplikasi sisi server |
| Cache | Kode aplikasi sisi server |
Cookies
Cookies menyimpan data di seluruh permintaan. Karena cookiedikirim 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 cookieterbatas yang tersedia untuk setiap domain.
Karena cookiedapat diubah, mereka harus divalidasi oleh aplikasi. Cookies dapat dihapus oleh pengguna dan kedaluwarsa pada klien. Namun, cookieumumnya merupakan bentuk persistensi data yang paling tahan lama pada klien.
Cookies 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 pengguna yang dipersonalisasi, seperti warna latar belakang situs web pilihan mereka.
Lihat Peraturan Perlindungan Data Umum (GDPR) Uni Eropa saat menerbitkan cookiedan berurusan dengan masalah privasi. 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.
- Sesi cookiedihapus saat 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 ISession.Clear implementasi dipanggil 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.
- cookieStatus 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 menyimpan data sensitif dalam status sesi. Pengguna mungkin tidak menutup browser dan menghapus sesi cookie. Beberapa browser mempertahankan sesi cookieyang 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 di memori server tempat aplikasi berada. Dalam skenario farm server:
- Gunakan sesi lengket untuk mengikat setiap sesi ke instans aplikasi tertentu di server individual. Azure App Service menggunakan Perutean Permintaan Aplikasi (ARR) untuk menerapkan sesi lengket secara default. Namun, sesi lengket dapat memengaruhi skalabilitas dan pembaruan aplikasi web yang rumit. Pendekatan yang lebih baik adalah menggunakan Redis atau cache terdistribusi 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 sesi cookiedi setiap komputer. Untuk informasi selengkapnya, lihat ASP.NET Gambaran Umum Perlindungan Data Inti dan Penyedia penyimpanan utama.
Mengonfigurasi status sesi
Paket Microsoft.AspNetCore.Session :
- Disertakan secara implisit oleh kerangka kerja.
- Menyediakan middleware untuk mengelola status sesi.
Untuk mengaktifkan middleware sesi, Program.cs harus berisi:
- IDistributedCache Salah satu cache memori. Implementasi
IDistributedCachedigunakan sebagai penyimpanan dukungan 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 IDistributedCachedalam memori default :
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 singkat untuk menyederhanakan pengujian.
Urutan middleware penting. Panggil 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 , Set, atau Remove . Jika LoadAsync tidak dipanggil terlebih dahulu, catatan 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 memberikan pengecualian jika LoadAsync metode tidak dipanggil sebelum TryGetValue, , Setatau 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 default ke true. IsEssential default ke false. |
| IdleTimeout | IdleTimeout menunjukkan berapa lama sesi dapat menganggur 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 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 diberi nama .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 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 ada di Microsoft.AspNetCore.Http namespace.
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 ISessionekstensi . Jenis kompleks harus diserialisasikan oleh pengguna menggunakan mekanisme lain, seperti JSAKTIF.
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));
}
}
}
TempData
ASP.NET Core mengekspos RazorHalaman 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 adalah:
- Berguna untuk pengalihan saat data diperlukan untuk lebih dari satu permintaan.
- Diimplementasikan oleh
TempDatapenyedia menggunakan cookiestatus s atau 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 di cookies.
Data cookie dienkripsi menggunakan IDataProtector, dikodekan dengan Base64UrlTextEncoder, lalu dipotong. Ukuran maksimum cookie kurang dari 4096 byte karena enkripsi dan penggugusan. 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 untuk setiap permintaan yang membawa TempData. Jika tidak, status sesi penyedia TempData dapat bermanfaat untuk menghindari round-tripping sejumlah besar data di setiap permintaan sampai 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 ASP.NET Gambaran Umum Perlindungan Data Inti dan Penyedia penyimpanan utama.
Sebagian besar klien web seperti browser web memberlakukan batasan pada ukuran maksimum masing-masing cookie dan jumlah cookietotal. Saat menggunakan cookie penyedia TempData, verifikasi aplikasi tidak akan melebihi batas ini. Pertimbangkan ukuran total data. Mempertanggungjawabkan cookie peningkatan ukuran karena enkripsi dan penggugusan.
Mengonfigurasi penyedia TempData
Penyedia cookieTempData berbasis diaktifkan secara default.
Untuk mengaktifkan penyedia TempData berbasis sesi, gunakan AddSessionStateTempDataProvider metode ekstensi. Hanya diperlukan satu panggilan ke AddSessionStateTempDataProvider :
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 formulir 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 ini sering digunakan untuk memungkinkan komponen atau middleware berkomunikasi ketika mereka beroperasi pada titik waktu yang berbeda selama permintaan dan tidak memiliki cara langsung untuk melewati 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, object dapat 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.
Kesalahan umum
"Tidak dapat mengatasi layanan untuk jenis 'Microsoft.Extensions.Caching.Distributed.IDistributedCache' saat mencoba mengaktifkan 'Microsoft.AspNetCore.Session.DistributedSessionStore'."
Hal ini biasanya disebabkan oleh gagal mengonfigurasi setidaknya satu
IDistributedCacheimplementasi. 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 dukungan tidak tersedia. Misalnya, pengguna menyimpan kedai belanja dalam sesi. Pengguna menambahkan item ke kerajinan tetapi penerapan gagal. Aplikasi tidak tahu tentang kegagalan sehingga melaporkan kepada pengguna bahwa item ditambahkan ke kelima mereka, yang tidak benar.
Pendekatan yang disarankan untuk memeriksa kesalahan adalah 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 dilemparkan dalam kondisi yang sama ketika penyimpanan data tidak tersedia.
SignalR dan keadaan sesi
SignalR aplikasi tidak boleh menggunakan status sesi untuk menyimpan informasi. SignalR aplikasi dapat menyimpan per status koneksi di Context.Items hub.
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 topik ini.
| Pendekatan penyimpanan | Mekanisme penyimpanan |
|---|---|
| CookieS | HTTP cookies. Dapat mencakup data yang disimpan menggunakan kode aplikasi sisi server. |
| Status sesi | HTTP cookies dan kode aplikasi sisi server |
| TempData | STATUS HTTP cookieatau sesi |
| String kueri | String kueri HTTP |
| Bidang tersembunyi | Bidang formulir HTTP |
| HttpContext.Items | Kode aplikasi sisi server |
| Cache | Kode aplikasi sisi server |
Cookies
Cookies menyimpan data di seluruh permintaan. Karena cookiedikirim 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 cookieterbatas yang tersedia untuk setiap domain.
Karena cookiedapat diubah, mereka harus divalidasi oleh aplikasi. Cookies dapat dihapus oleh pengguna dan kedaluwarsa pada klien. Namun, cookieumumnya merupakan bentuk persistensi data yang paling tahan lama pada klien.
Cookies 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 pengguna yang dipersonalisasi, seperti warna latar belakang situs web pilihan mereka.
Lihat Peraturan Perlindungan Data Umum (GDPR) Uni Eropa saat menerbitkan cookiedan berurusan dengan masalah privasi. 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.
- Sesi cookiedihapus saat 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 ISession.Clear implementasi dipanggil 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.
- cookieStatus 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 menyimpan data sensitif dalam status sesi. Pengguna mungkin tidak menutup browser dan menghapus sesi cookie. Beberapa browser mempertahankan sesi cookieyang 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 di memori server tempat aplikasi berada. Dalam skenario farm server:
- Gunakan sesi lengket untuk mengikat setiap sesi ke instans aplikasi tertentu di server individual. Azure App Service menggunakan Perutean Permintaan Aplikasi (ARR) untuk menerapkan sesi lengket secara default. Namun, sesi lengket dapat memengaruhi skalabilitas dan pembaruan aplikasi web yang rumit. Pendekatan yang lebih baik adalah menggunakan Redis atau cache terdistribusi 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 sesi cookiedi setiap komputer. Untuk informasi selengkapnya, lihat ASP.NET Gambaran Umum Perlindungan Data Inti dan Penyedia penyimpanan utama.
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
IDistributedCachedigunakan sebagai penyimpanan dukungan untuk sesi. Untuk informasi selengkapnya, lihat Penembolokan terdistribusi di ASP.NET Core. - Panggilan ke AddSession di
ConfigureServices. - Panggilan ke UseSession di
Configure.
Kode berikut menunjukkan cara menyiapkan penyedia sesi dalam memori dengan implementasi IDistributedCachedalam memori default :
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 singkat untuk menyederhanakan pengujian.
Urutan middleware penting. Panggil 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 , Set, atau Remove . Jika LoadAsync tidak dipanggil terlebih dahulu, catatan 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 memberikan pengecualian jika LoadAsync metode tidak dipanggil sebelum TryGetValue, , Setatau 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 default ke true. IsEssential default ke false. |
| IdleTimeout | IdleTimeout menunjukkan berapa lama sesi dapat menganggur 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 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 diberi nama .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 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 ada di Microsoft.AspNetCore.Http namespace.
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 ISessionekstensi . Jenis kompleks harus diserialisasikan oleh pengguna menggunakan mekanisme lain, seperti JSAKTIF.
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 RazorHalaman 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 adalah:
- Berguna untuk pengalihan saat data diperlukan untuk lebih dari satu permintaan.
- Diimplementasikan oleh
TempDatapenyedia menggunakan cookiestatus s atau 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 di cookies.
Data cookie dienkripsi menggunakan IDataProtector, dikodekan dengan Base64UrlTextEncoder, lalu dipotong. Ukuran maksimum cookie kurang dari 4096 byte karena enkripsi dan penggugusan. 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 untuk setiap permintaan yang membawa TempData. Jika tidak, status sesi penyedia TempData dapat bermanfaat untuk menghindari round-tripping sejumlah besar data di setiap permintaan sampai 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 utama).
Sebagian besar klien web seperti browser web memberlakukan batasan pada ukuran maksimum masing-masing cookie dan jumlah cookietotal. Saat menggunakan cookie penyedia TempData, verifikasi aplikasi tidak akan melebihi batas ini. Pertimbangkan ukuran total data. Mempertanggungjawabkan cookie peningkatan ukuran karena enkripsi dan penggugusan.
Mengonfigurasi penyedia TempData
Penyedia cookieTempData berbasis diaktifkan secara default.
Untuk mengaktifkan penyedia TempData berbasis sesi, gunakan AddSessionStateTempDataProvider metode ekstensi. Hanya diperlukan satu panggilan ke AddSessionStateTempDataProvider :
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 formulir 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 ini sering digunakan untuk memungkinkan komponen atau middleware berkomunikasi ketika mereka beroperasi pada titik waktu yang berbeda selama permintaan dan tidak memiliki cara langsung untuk melewati 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'."
Hal ini biasanya disebabkan oleh gagal mengonfigurasi setidaknya satu
IDistributedCacheimplementasi. 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 dukungan tidak tersedia. Misalnya, pengguna menyimpan kedai belanja dalam sesi. Pengguna menambahkan item ke kerajinan tetapi penerapan gagal. Aplikasi tidak tahu tentang kegagalan sehingga melaporkan kepada pengguna bahwa item ditambahkan ke kelima mereka, yang tidak benar.
Pendekatan yang disarankan untuk memeriksa kesalahan adalah 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 dilemparkan dalam kondisi yang sama ketika penyimpanan data tidak tersedia.
SignalR dan keadaan sesi
SignalR aplikasi tidak boleh menggunakan status sesi untuk menyimpan informasi. SignalR aplikasi dapat menyimpan per status koneksi di Context.Items hub.