Bagikan melalui


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 artikel 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

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.

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 jumlah cookieterbatas yang tersedia untuk setiap domain.

Karena cookietunduk pada perubahan, 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 yang dipersonalisasi pengguna, seperti warna latar belakang situs web pilihan mereka.

Lihat Peraturan Perlindungan Data Umum Uni Eropa (GDPR) saat menerbitkan cookiedan menangani 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 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.
  • 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.
  • Catatan: Tidak ada penggantian untuk fitur sesi yang cookielebih sedikit 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 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 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 sesi cookiedi 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:

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, , 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 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. Sessiondiimplementasikan 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:

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 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));

        }
    }
}

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 adalah:

  • Berguna untuk pengalihan saat data diperlukan untuk lebih dari satu permintaan.
  • Diimplementasikan oleh TempData penyedia 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 dalam cookies.

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 cookietotal. 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

Melihat atau mengunduh kode sampel (cara mengunduh)

Menghosting ASP.NET Core di farm web

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
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

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.

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 jumlah cookieterbatas yang tersedia untuk setiap domain.

Karena cookietunduk pada perubahan, 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 yang dipersonalisasi pengguna, seperti warna latar belakang situs web pilihan mereka.

Lihat Peraturan Perlindungan Data Umum Uni Eropa (GDPR) saat menerbitkan cookiedan menangani 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 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.
  • 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 simpan 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 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 sesi cookiedi 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:

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, , 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 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. Sessiondiimplementasikan 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:

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 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 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 adalah:

  • Berguna untuk pengalihan saat data diperlukan untuk lebih dari satu permintaan.
  • Diimplementasikan oleh TempData penyedia 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 dalam cookies.

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 cookietotal. 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

Menghosting ASP.NET Core di farm web