ASP.NET Core’da oturum ve durum yönetimi

Rick Anderson, Kirk Larkin ve Diana LaRose tarafından

HTTP durum bilgisi olmayan bir protokoldür. Varsayılan olarak, HTTP istekleri kullanıcı değerlerini tutmayan bağımsız iletilerdir. Bu makalede, istekler arasındaki kullanıcı verilerini korumaya yönelik çeşitli yaklaşımlar açıklanmaktadır.

Durum yönetimi

Durum, çeşitli yaklaşımlar kullanılarak depolanabilir. Her yaklaşım bu makalenin devamında açıklanmıştır.

Depolama yaklaşımı Depolama mekanizması
Cookies HTTP cookies. Sunucu tarafı uygulama kodu kullanılarak depolanan verileri içerebilir.
Oturum durumu HTTP cookies ve sunucu tarafı uygulama kodu
TempData HTTP cookies veya oturum durumu
Sorgu dizeleri HTTP sorgu dizeleri
Gizli alanlar HTTP form alanları
HttpContext.Items Sunucu tarafı uygulama kodu
Önbellek Sunucu tarafı uygulama kodu

SignalR/Blazor Server ve HTTP bağlam tabanlı durum yönetimi

SignalR uygulamalar, bilgileri depolamak için kararlı bir HTTP bağlamı kullanan oturum durumu ve diğer durum yönetimi yaklaşımlarını kullanmamalıdır. SignalRuygulamalar bağlantı başına durumunu hub'da Context.Itemsdepolayabilir. Uygulamalar için daha fazla bilgi ve alternatif durum yönetimi yaklaşımları için Blazor Server bkz . ASP.NET Çekirdek Blazor durum yönetimi.

CookieS

Cookieverileri istekler arasında depolar. cookieS'ler her istekle birlikte gönderildiği için boyutları en düşük düzeyde tutulmalıdır. İdeal olan, içinde yalnızca bir tanımlayıcının, uygulama tarafından depolanan verilerle birlikte depolanmasıdır cookie . Çoğu tarayıcı boyutu 4096 baytla kısıtlar cookie . Her etki alanı için yalnızca sınırlı sayıda cookies kullanılabilir.

cookieBunlar üzerinde oynanmaya tabi olduğundan, uygulama tarafından doğrulanmalıdır. Cookiekullanıcılar tarafından silinebilir ve istemcilerde süresi dolabilir. Ancak, cookies genellikle istemcideki veri kalıcılığının en dayanıklı biçimidir.

Cookiegenellikle içeriğin bilinen bir kullanıcı için özelleştirildiği kişiselleştirme için kullanılır. Kullanıcı yalnızca tanımlanır ve çoğu durumda kimliği doğrulanmaz. cookie kullanıcının adını, hesap adını veya GUID gibi benzersiz kullanıcı kimliğini depolayabilir. cookie, kullanıcının tercih ettiği web sitesi arka plan rengi gibi kişiselleştirilmiş ayarlarına erişmek için kullanılabilir.

Gizlilik endişelerini oluştururken ve bunlarla ilgilenirken cookieAvrupa Birliği Genel Veri Koruma Düzenlemeleri'ne (GDPR) bakın. Daha fazla bilgi için bkz . ASP.NET Core'da Genel Veri Koruma Yönetmeliği (GDPR) desteği.

Oturum durumu

Oturum durumu, kullanıcı bir web uygulamasına göz atarken kullanıcı verilerinin depolanmasına yönelik bir ASP.NET Core senaryosudur. Oturum durumu, istemciden gelen istekler arasında verileri kalıcı hale getirmek için uygulama tarafından tutulan bir depo kullanır. Oturum verileri bir önbellek tarafından yedeklenmiştir ve kısa ömürlü veriler olarak kabul edilir. Site, oturum verileri olmadan çalışmaya devam etmelidir. Kritik uygulama verileri kullanıcı veritabanında depolanmalı ve yalnızca performans iyileştirmesi olarak oturumda önbelleğe alınmalıdır.

Bir Hub, HTTP bağlamından bağımsız olarakSignalRyürütülebileceğinden oturum uygulamalarda desteklenmezSignalR. Örneğin, uzun bir yoklama isteği, isteğin HTTP bağlamının ömründen uzun bir süre boyunca bir hub tarafından açık tutulduğunda bu durum oluşabilir.

ASP.NET Core, istemciye oturum kimliği içeren bir cookie sağlayarak oturum durumunu korur. Oturum cookie kimliği:

  • Her istekle birlikte uygulamaya gönderilir.
  • Uygulama tarafından oturum verilerini getirmek için kullanılır.

Oturum durumu aşağıdaki davranışları sergiler:

  • Oturum cookie tarayıcıya özgüdür. Oturumlar tarayıcılar arasında paylaşılamaz.
  • Tarayıcı oturumu cookiesona erdiğinde oturumlar silinir.
  • cookie Süresi dolmuş bir oturum için bir alınırsa, aynı oturumu kullanan yeni bir oturum cookieoluşturulur.
  • Boş oturumlar korunmaz. Oturumu istekler arasında kalıcı hale getirmek için oturumda en az bir değer ayarlanmalıdır. Bir oturum korunmadığında, her yeni istek için yeni bir oturum kimliği oluşturulur.
  • Uygulama, son istek sonrasında oturumu sınırlı bir süre boyunca saklar. Uygulama oturum zaman aşımını ayarlar veya varsayılan 20 dakika değerini kullanır. Oturum durumu, kullanıcı verilerini depolamak için idealdir:
    • Bu belirli bir oturuma özgü.
    • Verilerin oturumlar arasında kalıcı depolama gerektirmediği durumlar.
  • Uygulama çağrıldığında veya oturumun ISession.Clear süresi dolduğunda oturum verileri silinir.
  • Uygulama koduna istemci tarayıcının kapatıldığını veya istemcide oturumun cookie silindiğini veya süresinin dolduğunu bildiren varsayılan bir mekanizma yoktur.
  • Oturum durumu cookievarsayılan olarak temel olarak işaretlenmez. Site ziyaretçisi tarafından izlemeye izin verilmediği sürece oturum durumu işlevsel değildir. Daha fazla bilgi için bkz . ASP.NET Core'da Genel Veri Koruma Yönetmeliği (GDPR) desteği.
  • Not: Güvenli olmadığı kabul edildiğinden cookieve oturum düzeltme saldırılarına yol açabileceğinden, ASP.NET Framework'ün daha az oturum özelliğinin yerini almaması.

Uyarı

Hassas verileri oturum durumunda depolamayın. Kullanıcı tarayıcıyı kapatmayabilir ve oturumunu cookietemizlemeyebilir. Bazı tarayıcılar tarayıcı pencerelerinde geçerli oturumlar cookietutar. Oturum tek bir kullanıcıyla sınırlı olmayabilir. Sonraki kullanıcı aynı oturumla cookieuygulamaya göz atmaya devam edebilir.

Bellek içi önbellek sağlayıcısı, oturum verilerini uygulamanın bulunduğu sunucunun belleğinde depolar. Sunucu grubu senaryosunda:

  • Her oturumu tek bir sunucudaki belirli bir uygulama örneğine bağlamak için yapışkan oturumları kullanın. Azure Uygulaması Hizmeti, yapışkan oturumları varsayılan olarak zorlamak için Uygulama İsteği Yönlendirmesi'ne (ARR) sahiptir. Ancak, yapışkan oturumlar ölçeklenebilirliği etkileyebilir ve web uygulaması güncelleştirmelerini karmaşıklaştırabilir. Daha iyi bir yaklaşım, yapışkan oturumlar gerektirmeyen bir Redis veya SQL Server dağıtılmış önbelleği kullanmaktır. Daha fazla bilgi için bkz . ASP.NET Core'da dağıtılmış önbelleğe alma.
  • Oturum cookie aracılığıyla IDataProtectorşifrelenir. Veri Koruması, her makinedeki oturumları cookieokuyacak şekilde düzgün yapılandırılmalıdır. Daha fazla bilgi için bkz . ASP.NET Core Data Protection'a Genel Bakış ve Anahtar depolama sağlayıcıları.

Oturum durumunu yapılandırma

Oturum durumunu yönetmek için ara yazılım çerçeveye dahil edilir. Oturum ara yazılımını etkinleştirmek için şunları Program.cs içermelidir:

Aşağıdaki kodda, varsayılan bellek içi uygulamasıyla bellek içi oturum sağlayıcısının nasıl ayarlanacağı gösterilmektedir 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();

Yukarıdaki kod, testi basitleştirmek için kısa bir zaman aşımı ayarlar.

Ara yazılım sırası önemlidir. ve sonrasında UseRouting ve MapDefaultControllerRoute öncesinde MapRazorPages öğesini arayınUseSession. Bkz . Ara Yazılım Sıralama.

HttpContext.Session , oturum durumu yapılandırıldıktan sonra kullanılabilir.

HttpContext.Session çağrılmadan önce UseSession erişilemiyor.

Uygulama yanıt akışına yazmaya başladıktan sonra yeni oturum içeren yeni bir oturum cookie oluşturulamaz. Özel durum web sunucusu günlüğüne kaydedilir ve tarayıcıda görüntülenmez.

Oturum durumunu zaman uyumsuz olarak yükleme

ASP.NET Core'daki varsayılan oturum sağlayıcısı, yalnızca yöntemin , veya yöntemlerinden önce açıkça çağrılırsa temel alınan IDistributedCache yedekleme deposundaki SetISession.LoadAsyncTryGetValueoturum kayıtlarını zaman uyumsuz olarak yükler.Remove İlk olarak çağrılmazsa LoadAsync , temel oturum kaydı zaman uyumlu olarak yüklenir ve bu da büyük ölçekte bir performans cezasına neden olabilir.

Uygulamaların bu deseni zorlamasını DistributedSessionStore sağlamak için ve DistributedSession uygulamalarını, yöntemi , veya Remove'den önce TryGetValueSetçağrılmadıysa LoadAsync özel durum oluşturan sürümlerle sarmalar. Sarmalanmış sürümleri hizmetler kapsayıcısında kaydedin.

Oturum seçenekleri

Oturum varsayılanlarını geçersiz kılmak için kullanın SessionOptions.

Seçenek Açıklama
Cookie oluşturmak cookieiçin kullanılan ayarları belirler. Name () olarak varsayılan değere SessionDefaults.CookieName sahiptir.AspNetCore.Session. Path () olarak varsayılan değere SessionDefaults.CookiePath sahiptir/. SameSite () olarak varsayılan değere SameSiteMode.Lax sahiptir1. HttpOnly varsayılan olarak true şeklinde ayarlanır. IsEssential varsayılan olarak false şeklinde ayarlanır.
IdleTimeout , IdleTimeout içeriği terk edilmeden önce oturumun ne kadar süreyle boşta olabileceğini gösterir. Her oturum erişimi zaman aşımını sıfırlar. Bu ayar yalnızca oturumun içeriği için geçerlidir, için geçerli değildir cookie. Varsayılan değer 20 dakikadır.
IOTimeout Bir oturumun mağazadan yüklenmesine veya depoya geri işlenmesine izin verilen maksimum süre. Bu ayar yalnızca zaman uyumsuz işlemler için geçerli olabilir. Bu zaman aşımı kullanılarak InfiniteTimeSpandevre dışı bırakılabilir. Varsayılan değer 1 dakikadır.

Oturum, tek bir tarayıcıdan gelen istekleri izlemek ve tanımlamak için bir kullanır cookie . Bu, cookie varsayılan olarak olarak olarak adlandırılır .AspNetCore.Sessionve yolunu /kullanır. Varsayılan değer cookie bir etki alanı belirtmediğinden, sayfadaki istemci tarafı betiğinde kullanılabilir duruma getirilmez ( HttpOnly varsayılan olarak olarak belirtildiğinden true).

Oturum varsayılanlarını geçersiz kılmak cookie için kullanın 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();

Uygulama, sunucunun önbelleğindeki IdleTimeout içeriği bırakılmadan önce oturumun ne kadar süreyle boşta olabileceğini belirlemek için özelliğini kullanır. Bu özellik süre sonu özelliğinden cookie bağımsızdır. Oturum Ara Yazılımı'nı geçen her istek zaman aşımını sıfırlar.

Oturum durumu kilitleniyor. İki istek aynı anda bir oturumun içeriğini değiştirmeye çalışırsa, son istek ilkini geçersiz kılar. Session tutarlı bir oturum olarak uygulanır ve bu da tüm içeriğin birlikte depolandığı anlamına gelir. İki istek farklı oturum değerlerini değiştirmeye çalıştığında, son istek ilk istek tarafından yapılan oturum değişikliklerini geçersiz kılabilir.

Oturum değerlerini ayarlama ve alma

Oturum durumuna pages RazorPageModel sınıfından veya ile HttpContext.SessionMVC Controller sınıfından erişilir. Bu özellik bir ISession uygulamadır.

Uygulama, ISession tamsayı ve dize değerlerini ayarlamak ve almak için çeşitli uzantı yöntemleri sağlar. Uzantı yöntemleri ad alanındadır Microsoft.AspNetCore.Http .

ISession uzantı yöntemleri:

Aşağıdaki örnek, bir Razor Sayfalar sayfasında anahtarın IndexModel.SessionKeyName (_Nameörnek uygulamada) oturum değerini alır:

@page
@using Microsoft.AspNetCore.Http
@model IndexModel

...

Name: @HttpContext.Session.GetString(IndexModel.SessionKeyName)

Aşağıdaki örnekte tamsayı ve dize ayarlama ve alma gösterilmektedir:

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

Aşağıdaki işaretleme bir Razor Sayfadaki oturum değerlerini görüntüler:

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


Bellek içi önbellek kullanılırken bile dağıtılmış önbellek senaryosunun etkinleştirilmesi için tüm oturum verilerinin seri hale getirilmesi gerekir. Dize ve tamsayı serileştiricileri uzantısı yöntemleri ISessiontarafından sağlanır. Karmaşık türler, kullanıcı tarafından ON gibi JSbaşka bir mekanizma kullanılarak seri hale getirilmelidir.

Nesneleri seri hale getirmek için aşağıdaki örnek kodu kullanın:

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

Aşağıdaki örnekte, sınıfıyla seri hale getirilebilir bir nesne ayarlama ve alma işlemi gösterilmektedir SessionExtensions :

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

        }
    }
}

Uyarı

Serileştirilmiş nesnelerde oluşabilecek birçok sorun olduğundan, canlı bir nesneyi oturumda depolamak dikkatli kullanılmalıdır. Daha fazla bilgi için bkz . Oturumların nesneleri depolamasına izin verilmelidir (dotnet/aspnetcore #18159).

TempData

ASP.NET Core, Pages TempData veya Controller'ı RazorTempDatakullanıma sunar. Bu özellik, başka bir istekte okunana kadar verileri depolar. Keep (String) ve Peek(string) yöntemleri, isteğin sonunda silinmeden verileri incelemek için kullanılabilir. Saklama, sözlükteki tüm öğeleri bekletmek için işaretler. TempData şudur:

  • Tek bir istekten fazlası için veri gerektiğinde yeniden yönlendirme için kullanışlıdır.
  • Sağlayıcılar tarafından TempData s veya oturum durumu kullanılarak cookieuygulanır.

TempData örnekleri

Müşteri oluşturan aşağıdaki sayfayı göz önünde bulundurun:

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

Aşağıdaki sayfada görüntülenir TempData["Message"]:

@page
@model IndexModel

<h1>Peek Contacts</h1>

@{
    if (TempData.Peek("Message") != null)
    {
        <h3>Message: @TempData.Peek("Message")</h3>
    }
}

@*Content removed for brevity.*@

Önceki işaretlemede, isteğin TempData["Message"]sonunda kullanıldığından silinmezPeek. Sayfa yenilendiğinde içeriğini TempData["Message"]görüntüler.

Aşağıdaki işaretleme önceki koda benzer, ancak isteğin sonundaki verileri korumak için kullanır Keep :

@page
@model IndexModel

<h1>Contacts Keep</h1>

@{
    if (TempData["Message"] != null)
    {
        <h3>Message: @TempData["Message"]</h3>
    }
    TempData.Keep("Message");
}

@*Content removed for brevity.*@

IndexPeek ve IndexKeep sayfaları arasında gezinmek silinmezTempData["Message"].

Aşağıdaki kod görüntülenir TempData["Message"], ancak isteğin TempData["Message"] sonunda silinir:

@page
@model IndexModel

<h1>Index no Keep or Peek</h1>

@{
    if (TempData["Message"] != null)
    {
        <h3>Message: @TempData["Message"]</h3>
    }
}

@*Content removed for brevity.*@

TempData sağlayıcıları

cookieTabanlı TempData sağlayıcısı varsayılan olarak TempData'yi s içinde cookiedepolamak için kullanılır.

Veriler cookie ile kodlanmış Base64UrlTextEncoderve öbeklenmiş olarak kullanılarak IDataProtectorşifrelenir. Şifreleme ve öbekleme nedeniyle boyut üst cookie sınırı 4096 bayttan azdır. cookie Şifrelenmiş verilerin sıkıştırılması ve BREACH saldırıları gibi CRIME güvenlik sorunlarına yol açabileceğinden veriler sıkıştırılmıyor. Tabanlı TempData sağlayıcısı hakkında cookiedaha fazla bilgi için bkz CookieTempDataProvider. .

TempData sağlayıcısı seçme

TempData sağlayıcısını seçmek için dikkat edilmesi gereken birkaç nokta vardır:

  • Uygulama zaten oturum durumunu kullanıyor mu? Bu durumda TempData sağlayıcısının oturum durumunun kullanılması, uygulamanın veri boyutunu aşan ek bir maliyeti yoktur.
  • Uygulama TempData'yı yalnızca 500 bayta kadar nispeten az miktarda veri için mi kullanıyor? Bu durumda, cookie TempData sağlayıcısı TempData taşıyan her isteğe küçük bir maliyet ekler. Değilse, TempData oturum durumu sağlayıcısı TempData tüketilene kadar her istekte büyük miktarda veriyi yuvarlamaktan kaçınmak yararlı olabilir.
  • Uygulama birden çok sunucudaki bir sunucu grubunda mı çalışıyor? Bu durumda, TempData sağlayıcısını cookie Data Protection dışında kullanmak için ek yapılandırma gerekmez. Daha fazla bilgi için bkz . ASP.NET Core Data Protection'a Genel Bakış ve Anahtar depolama sağlayıcıları.

Web tarayıcıları gibi çoğu web istemcisi, her cookie birinin boyut üst sınırına ve toplam s sayısına cookiesınırlar uygular. TempData sağlayıcısını cookie kullanırken uygulamanın bu sınırları aşmadığını doğrulayın. Verilerin toplam boyutunu göz önünde bulundurun. Şifreleme ve öbekleme nedeniyle boyut artışlarını cookie hesaba katın.

TempData sağlayıcısını yapılandırma

cookieTabanlı TempData sağlayıcısı varsayılan olarak etkindir.

Oturum tabanlı TempData sağlayıcısını etkinleştirmek için uzantı yöntemini kullanın AddSessionStateTempDataProvider . Yalnızca bir çağrı AddSessionStateTempDataProvider gereklidir:

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

Sorgu dizeleri

Sınırlı miktarda veri, yeni isteğin sorgu dizesine eklenerek bir istekten diğerine geçirilebilir. Bu, ekli duruma sahip bağlantıların e-posta veya sosyal ağlar aracılığıyla paylaşılmasını sağlayan kalıcı bir şekilde durumu yakalamak için kullanışlıdır. URL sorgu dizeleri genel olduğundan, hassas veriler için hiçbir zaman sorgu dizelerini kullanmayın.

Sorgu dizelerindeki veriler dahil olmak üzere istenmeyen paylaşıma ek olarak, uygulamayı Siteler Arası İstek Sahteciliği (CSRF) saldırılarına maruz bırakabilirsiniz. Korunan tüm oturum durumları CSRF saldırılarına karşı korunmalıdır. Daha fazla bilgi için, bkz. ASP.NET Core'da Siteler Arası İstek Sahteciliği (XSRF/CSRF) saldırılarını önleme.

Gizli alanlar

Veriler gizli form alanlarına kaydedilebilir ve sonraki istekte geri gönderilebilir. Bu, çok sayfalı formlarda yaygındır. İstemci potansiyel olarak verilerle oynanabileceğinden, uygulamanın gizli alanlarda depolanan verileri her zaman yeniden doğrulaması gerekir.

HttpContext.Items

Koleksiyon HttpContext.Items , tek bir isteği işlerken verileri depolamak için kullanılır. Bir istek işlendikten sonra koleksiyonun içeriği atılır. Koleksiyon Items genellikle bileşenlerin veya ara yazılımların bir istek sırasında farklı noktalarda çalıştıklarında iletişim kurmasına izin vermek için kullanılır ve parametreleri geçirmek için doğrudan bir yolu yoktur.

Aşağıdaki örnekte ara yazılım koleksiyona Items eklerisVerified:

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

Yalnızca tek bir uygulamada kullanılan ara yazılımlarda sabit string anahtar kullanmanın anahtar çakışmasına neden olması pek olası değil. Ancak, bir anahtar çarpışması olasılığını tamamen önlemek için, bir object öğe anahtarı olarak kullanılabilir. Bu yaklaşım özellikle uygulamalar arasında paylaşılan ve kodda anahtar dizelerinin kullanımını ortadan kaldırma avantajına sahip ara yazılım için kullanışlıdır. Aşağıdaki örnekte, ara yazılım sınıfında tanımlanan bir object anahtarın nasıl kullanılacağı gösterilmektedir:

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

Diğer kod, ara yazılım sınıfı tarafından kullanıma sunulan anahtarı kullanarak içinde HttpContext.Items depolanan değere erişebilir:

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!");
    }
}

Önbellek

Önbelleğe Alma, verileri depolamak ve almak için verimli bir yoldur. Uygulama, önbelleğe alınan öğelerin ömrünü denetleyebilir. Daha fazla bilgi için bkz . ASP.NET Core'da yanıt önbelleğe alma.

Önbelleğe alınan veriler belirli bir istek, kullanıcı veya oturumla ilişkili değildir. Diğer kullanıcı istekleri tarafından alınabilecek kullanıcıya özgü verileri önbelleğe almayın.

Uygulama genelindeki verileri önbelleğe almak için bkz . ASP.NET Core'da bellek içi önbellek.

Oturum durumunu denetleme

ISession.IsAvailable geçici hataları denetlemeye yöneliktir. Oturum ara yazılımı çalıştırmadan önce çağrılması IsAvailable bir InvalidOperationExceptionoluşturur.

Oturum kullanılabilirliğini test etmek için gereken kitaplıklar kullanabilir HttpContext.Features.Get<ISessionFeature>()?.Session != null.

Sık karşılaşılan hatalar

  • "'Microsoft.Extensions' türü için hizmet çözümlenemiyor. Önbelleğe Alma. 'Microsoft.AspNetCore.Session.DistributedSessionStore' etkinleştirilmeye çalışılırken Distributed.IDistributedCache'.

    Bunun nedeni genellikle en az bir IDistributedCache uygulamanın yapılandırılmamış olmasıdır. Daha fazla bilgi için bkz . ASP.NET Core'da dağıtılmış önbelleğe alma ve ASP.NET Core'da bellek içi önbellek.

Oturum ara yazılımı bir oturumu kalıcı hale getirmek için başarısız olursa:

  • Ara yazılım özel durumu günlüğe kaydeder ve istek normal şekilde devam eder.
  • Bu, öngörülemeyen davranışlara yol açar.

Yedekleme deposu kullanılamıyorsa oturum ara yazılımı oturumu kalıcı hale getiremez. Örneğin, bir kullanıcı alışveriş sepetini oturumda depolar. Kullanıcı sepete bir öğe ekler, ancak işleme başarısız olur. Uygulama hatadan haberdar olmadığından, kullanıcıya öğenin sepetine eklendiğini bildirir ve bu doğru değildir.

Hataları denetlemek için önerilen yaklaşım, uygulama oturuma yazmayı bitirdiğinde çağrısı await feature.Session.CommitAsync yapmaktır. CommitAsync , yedekleme deposu kullanılamıyorsa bir özel durum oluşturur. Başarısız olursa CommitAsync , uygulama özel durumu işleyebilir. LoadAsync veri deposu kullanılamadığında aynı koşullar altında atar.

Ek kaynaklar

Örnek kodu görüntüleme veya indirme (indirme)

Web grubunda ASP.NET Core barındırma

Rick Anderson, Kirk Larkin ve Diana LaRose tarafından

HTTP durum bilgisi olmayan bir protokoldür. Varsayılan olarak, HTTP istekleri kullanıcı değerlerini tutmayan bağımsız iletilerdir. Bu makalede, istekler arasındaki kullanıcı verilerini korumaya yönelik çeşitli yaklaşımlar açıklanmaktadır.

Örnek kodu görüntüleme veya indirme (indirme)

Durum yönetimi

Durum, çeşitli yaklaşımlar kullanılarak depolanabilir. Her yaklaşım bu makalenin devamında açıklanmıştır.

Depolama yaklaşımı Depolama mekanizması
Cookies HTTP cookies. Sunucu tarafı uygulama kodu kullanılarak depolanan verileri içerebilir.
Oturum durumu HTTP cookies ve sunucu tarafı uygulama kodu
TempData HTTP cookies veya oturum durumu
Sorgu dizeleri HTTP sorgu dizeleri
Gizli alanlar HTTP form alanları
HttpContext.Items Sunucu tarafı uygulama kodu
Önbellek Sunucu tarafı uygulama kodu

SignalR/Blazor Server ve HTTP bağlam tabanlı durum yönetimi

SignalR uygulamalar, bilgileri depolamak için kararlı bir HTTP bağlamı kullanan oturum durumu ve diğer durum yönetimi yaklaşımlarını kullanmamalıdır. SignalRuygulamalar bağlantı başına durumunu hub'da Context.Itemsdepolayabilir. Uygulamalar için daha fazla bilgi ve alternatif durum yönetimi yaklaşımları için Blazor Server bkz . ASP.NET Çekirdek Blazor durum yönetimi.

CookieS

Cookieverileri istekler arasında depolar. cookieS'ler her istekle birlikte gönderildiği için boyutları en düşük düzeyde tutulmalıdır. İdeal olan, içinde yalnızca bir tanımlayıcının, uygulama tarafından depolanan verilerle birlikte depolanmasıdır cookie . Çoğu tarayıcı boyutu 4096 baytla kısıtlar cookie . Her etki alanı için yalnızca sınırlı sayıda cookies kullanılabilir.

cookieBunlar üzerinde oynanmaya tabi olduğundan, uygulama tarafından doğrulanmalıdır. Cookiekullanıcılar tarafından silinebilir ve istemcilerde süresi dolabilir. Ancak, cookies genellikle istemcideki veri kalıcılığının en dayanıklı biçimidir.

Cookiegenellikle içeriğin bilinen bir kullanıcı için özelleştirildiği kişiselleştirme için kullanılır. Kullanıcı yalnızca tanımlanır ve çoğu durumda kimliği doğrulanmaz. cookie kullanıcının adını, hesap adını veya GUID gibi benzersiz kullanıcı kimliğini depolayabilir. cookie, kullanıcının tercih ettiği web sitesi arka plan rengi gibi kişiselleştirilmiş ayarlarına erişmek için kullanılabilir.

Gizlilik endişelerini oluştururken ve bunlarla ilgilenirken cookieAvrupa Birliği Genel Veri Koruma Düzenlemeleri'ne (GDPR) bakın. Daha fazla bilgi için bkz . ASP.NET Core'da Genel Veri Koruma Yönetmeliği (GDPR) desteği.

Oturum durumu

Oturum durumu, kullanıcı bir web uygulamasına göz atarken kullanıcı verilerinin depolanmasına yönelik bir ASP.NET Core senaryosudur. Oturum durumu, istemciden gelen istekler arasında verileri kalıcı hale getirmek için uygulama tarafından tutulan bir depo kullanır. Oturum verileri bir önbellek tarafından yedeklenmiştir ve kısa ömürlü veriler olarak kabul edilir. Site, oturum verileri olmadan çalışmaya devam etmelidir. Kritik uygulama verileri kullanıcı veritabanında depolanmalı ve yalnızca performans iyileştirmesi olarak oturumda önbelleğe alınmalıdır.

Bir Hub, HTTP bağlamından bağımsız olarakSignalRyürütülebileceğinden oturum uygulamalarda desteklenmezSignalR. Örneğin, uzun bir yoklama isteği, isteğin HTTP bağlamının ömründen uzun bir süre boyunca bir hub tarafından açık tutulduğunda bu durum oluşabilir.

ASP.NET Core, istemciye oturum kimliği içeren bir cookie sağlayarak oturum durumunu korur. Oturum cookie kimliği:

  • Her istekle birlikte uygulamaya gönderilir.
  • Uygulama tarafından oturum verilerini getirmek için kullanılır.

Oturum durumu aşağıdaki davranışları sergiler:

  • Oturum cookie tarayıcıya özgüdür. Oturumlar tarayıcılar arasında paylaşılamaz.
  • Tarayıcı oturumu cookiesona erdiğinde oturumlar silinir.
  • cookie Süresi dolmuş bir oturum için bir alınırsa, aynı oturumu kullanan yeni bir oturum cookieoluşturulur.
  • Boş oturumlar korunmaz. Oturumu istekler arasında kalıcı hale getirmek için oturumda en az bir değer ayarlanmalıdır. Bir oturum korunmadığında, her yeni istek için yeni bir oturum kimliği oluşturulur.
  • Uygulama, son istek sonrasında oturumu sınırlı bir süre boyunca saklar. Uygulama oturum zaman aşımını ayarlar veya varsayılan 20 dakika değerini kullanır. Oturum durumu, kullanıcı verilerini depolamak için idealdir:
    • Bu belirli bir oturuma özgü.
    • Verilerin oturumlar arasında kalıcı depolama gerektirmediği durumlar.
  • Uygulama çağrıldığında veya oturumun ISession.Clear süresi dolduğunda oturum verileri silinir.
  • Uygulama koduna istemci tarayıcının kapatıldığını veya istemcide oturumun cookie silindiğini veya süresinin dolduğunu bildiren varsayılan bir mekanizma yoktur.
  • Oturum durumu cookievarsayılan olarak temel olarak işaretlenmez. Site ziyaretçisi tarafından izlemeye izin verilmediği sürece oturum durumu işlevsel değildir. Daha fazla bilgi için bkz . ASP.NET Core'da Genel Veri Koruma Yönetmeliği (GDPR) desteği.

Uyarı

Hassas verileri oturum durumunda depolamayın. Kullanıcı tarayıcıyı kapatmayabilir ve oturumunu cookietemizlemeyebilir. Bazı tarayıcılar tarayıcı pencerelerinde geçerli oturumlar cookietutar. Oturum tek bir kullanıcıyla sınırlı olmayabilir. Sonraki kullanıcı aynı oturumla cookieuygulamaya göz atmaya devam edebilir.

Bellek içi önbellek sağlayıcısı, oturum verilerini uygulamanın bulunduğu sunucunun belleğinde depolar. Sunucu grubu senaryosunda:

  • Her oturumu tek bir sunucudaki belirli bir uygulama örneğine bağlamak için yapışkan oturumları kullanın. Azure Uygulaması Hizmeti, yapışkan oturumları varsayılan olarak zorlamak için Uygulama İsteği Yönlendirmesi'ne (ARR) sahiptir. Ancak, yapışkan oturumlar ölçeklenebilirliği etkileyebilir ve web uygulaması güncelleştirmelerini karmaşıklaştırabilir. Daha iyi bir yaklaşım, yapışkan oturumlar gerektirmeyen bir Redis veya SQL Server dağıtılmış önbelleği kullanmaktır. Daha fazla bilgi için bkz . ASP.NET Core'da dağıtılmış önbelleğe alma.
  • Oturum cookie aracılığıyla IDataProtectorşifrelenir. Veri Koruması, her makinedeki oturumları cookieokuyacak şekilde düzgün yapılandırılmalıdır. Daha fazla bilgi için bkz . ASP.NET Core Data Protection'a Genel Bakış ve Anahtar depolama sağlayıcıları.

Oturum durumunu yapılandırma

Microsoft.AspNetCore.Session paketi:

  • Çerçeve tarafından örtük olarak dahil edilir.
  • Oturum durumunu yönetmek için ara yazılım sağlar.

Oturum ara yazılımını etkinleştirmek için şunları Startup içermelidir:

  • Bellek önbelleklerinden herhangi biri IDistributedCache . Uygulama IDistributedCache , oturum için bir yedekleme deposu olarak kullanılır. Daha fazla bilgi için bkz . ASP.NET Core'da dağıtılmış önbelleğe alma.
  • içinde ConfigureServicesöğesine AddSession yapılan bir çağrı.
  • içinde Configureöğesine UseSession yapılan bir çağrı.

Aşağıdaki kodda, varsayılan bellek içi uygulamasıyla bellek içi oturum sağlayıcısının nasıl ayarlanacağı gösterilmektedir 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();
        });
    }
}

Yukarıdaki kod, testi basitleştirmek için kısa bir zaman aşımı ayarlar.

Ara yazılım sırası önemlidir. 'den sonra UseRouting ve öncesinde UseEndpointsçağrısında bulunurUseSession. Bkz . Ara Yazılım Sıralama.

HttpContext.Session , oturum durumu yapılandırıldıktan sonra kullanılabilir.

HttpContext.Session çağrılmadan önce UseSession erişilemiyor.

Uygulama yanıt akışına yazmaya başladıktan sonra yeni oturum içeren yeni bir oturum cookie oluşturulamaz. Özel durum web sunucusu günlüğüne kaydedilir ve tarayıcıda görüntülenmez.

Oturum durumunu zaman uyumsuz olarak yükleme

ASP.NET Core'daki varsayılan oturum sağlayıcısı, yalnızca yöntemin , veya yöntemlerinden önce açıkça çağrılırsa temel alınan IDistributedCache yedekleme deposundaki SetISession.LoadAsyncTryGetValueoturum kayıtlarını zaman uyumsuz olarak yükler.Remove İlk olarak çağrılmazsa LoadAsync , temel oturum kaydı zaman uyumlu olarak yüklenir ve bu da büyük ölçekte bir performans cezasına neden olabilir.

Uygulamaların bu deseni zorlamasını DistributedSessionStore sağlamak için ve DistributedSession uygulamalarını, yöntemi , veya Remove'den önce TryGetValueSetçağrılmadıysa LoadAsync özel durum oluşturan sürümlerle sarmalar. Sarmalanmış sürümleri hizmetler kapsayıcısında kaydedin.

Oturum seçenekleri

Oturum varsayılanlarını geçersiz kılmak için kullanın SessionOptions.

Seçenek Açıklama
Cookie oluşturmak cookieiçin kullanılan ayarları belirler. Name () olarak varsayılan değere SessionDefaults.CookieName sahiptir.AspNetCore.Session. Path () olarak varsayılan değere SessionDefaults.CookiePath sahiptir/. SameSite () olarak varsayılan değere SameSiteMode.Lax sahiptir1. HttpOnly varsayılan olarak true şeklinde ayarlanır. IsEssential varsayılan olarak false şeklinde ayarlanır.
IdleTimeout , IdleTimeout içeriği terk edilmeden önce oturumun ne kadar süreyle boşta olabileceğini gösterir. Her oturum erişimi zaman aşımını sıfırlar. Bu ayar yalnızca oturumun içeriği için geçerlidir, için geçerli değildir cookie. Varsayılan değer 20 dakikadır.
IOTimeout Bir oturumun mağazadan yüklenmesine veya depoya geri işlenmesine izin verilen maksimum süre. Bu ayar yalnızca zaman uyumsuz işlemler için geçerli olabilir. Bu zaman aşımı kullanılarak InfiniteTimeSpandevre dışı bırakılabilir. Varsayılan değer 1 dakikadır.

Oturum, tek bir tarayıcıdan gelen istekleri izlemek ve tanımlamak için bir kullanır cookie . Bu, cookie varsayılan olarak olarak olarak adlandırılır .AspNetCore.Sessionve yolunu /kullanır. Varsayılan değer cookie bir etki alanı belirtmediğinden, sayfadaki istemci tarafı betiğinde kullanılabilir duruma getirilmez ( HttpOnly varsayılan olarak olarak belirtildiğinden true).

Oturum varsayılanlarını geçersiz kılmak cookie için kullanın 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();
}

Uygulama, sunucunun önbelleğindeki IdleTimeout içeriği bırakılmadan önce oturumun ne kadar süreyle boşta olabileceğini belirlemek için özelliğini kullanır. Bu özellik süre sonu özelliğinden cookie bağımsızdır. Oturum Ara Yazılımı'nı geçen her istek zaman aşımını sıfırlar.

Oturum durumu kilitleniyor. İki istek aynı anda bir oturumun içeriğini değiştirmeye çalışırsa, son istek ilkini geçersiz kılar. Session tutarlı bir oturum olarak uygulanır ve bu da tüm içeriğin birlikte depolandığı anlamına gelir. İki istek farklı oturum değerlerini değiştirmeye çalıştığında, son istek ilk istek tarafından yapılan oturum değişikliklerini geçersiz kılabilir.

Oturum değerlerini ayarlama ve alma

Oturum durumuna pages RazorPageModel sınıfından veya ile HttpContext.SessionMVC Controller sınıfından erişilir. Bu özellik bir ISession uygulamadır.

Uygulama, ISession tamsayı ve dize değerlerini ayarlamak ve almak için çeşitli uzantı yöntemleri sağlar. Uzantı yöntemleri ad alanındadır Microsoft.AspNetCore.Http .

ISession uzantı yöntemleri:

Aşağıdaki örnek, bir Razor Sayfalar sayfasında anahtarın IndexModel.SessionKeyName (_Nameörnek uygulamada) oturum değerini alır:

@page
@using Microsoft.AspNetCore.Http
@model IndexModel

...

Name: @HttpContext.Session.GetString(IndexModel.SessionKeyName)

Aşağıdaki örnekte tamsayı ve dize ayarlama ve alma gösterilmektedir:

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

Bellek içi önbellek kullanılırken bile dağıtılmış önbellek senaryosunun etkinleştirilmesi için tüm oturum verilerinin seri hale getirilmesi gerekir. Dize ve tamsayı serileştiricileri uzantısı yöntemleri ISessiontarafından sağlanır. Karmaşık türler, kullanıcı tarafından ON gibi JSbaşka bir mekanizma kullanılarak seri hale getirilmelidir.

Nesneleri seri hale getirmek için aşağıdaki örnek kodu kullanın:

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

Aşağıdaki örnekte, sınıfıyla seri hale getirilebilir bir nesne ayarlama ve alma işlemi gösterilmektedir SessionExtensions :

// Requires SessionExtensions from sample download.
if (HttpContext.Session.Get<DateTime>(SessionKeyTime) == default)
{
    HttpContext.Session.Set<DateTime>(SessionKeyTime, currentTime);
}

TempData

ASP.NET Core, Pages TempData veya Controller'ı RazorTempDatakullanıma sunar. Bu özellik, başka bir istekte okunana kadar verileri depolar. Keep (String) ve Peek(string) yöntemleri, isteğin sonunda silinmeden verileri incelemek için kullanılabilir. Saklama, sözlükteki tüm öğeleri bekletmek için işaretler. TempData şudur:

  • Tek bir istekten fazlası için veri gerektiğinde yeniden yönlendirme için kullanışlıdır.
  • Sağlayıcılar tarafından TempData s veya oturum durumu kullanılarak cookieuygulanır.

TempData örnekleri

Müşteri oluşturan aşağıdaki sayfayı göz önünde bulundurun:

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

Aşağıdaki sayfada görüntülenir TempData["Message"]:

@page
@model IndexModel

<h1>Peek Contacts</h1>

@{
    if (TempData.Peek("Message") != null)
    {
        <h3>Message: @TempData.Peek("Message")</h3>
    }
}

@*Content removed for brevity.*@

Önceki işaretlemede, isteğin TempData["Message"]sonunda kullanıldığından silinmezPeek. Sayfa yenilendiğinde içeriğini TempData["Message"]görüntüler.

Aşağıdaki işaretleme önceki koda benzer, ancak isteğin sonundaki verileri korumak için kullanır Keep :

@page
@model IndexModel

<h1>Contacts Keep</h1>

@{
    if (TempData["Message"] != null)
    {
        <h3>Message: @TempData["Message"]</h3>
    }
    TempData.Keep("Message");
}

@*Content removed for brevity.*@

IndexPeek ve IndexKeep sayfaları arasında gezinmek silinmezTempData["Message"].

Aşağıdaki kod görüntülenir TempData["Message"], ancak isteğin TempData["Message"] sonunda silinir:

@page
@model IndexModel

<h1>Index no Keep or Peek</h1>

@{
    if (TempData["Message"] != null)
    {
        <h3>Message: @TempData["Message"]</h3>
    }
}

@*Content removed for brevity.*@

TempData sağlayıcıları

cookieTabanlı TempData sağlayıcısı varsayılan olarak TempData'yi s içinde cookiedepolamak için kullanılır.

Veriler cookie ile kodlanmış Base64UrlTextEncoderve öbeklenmiş olarak kullanılarak IDataProtectorşifrelenir. Şifreleme ve öbekleme nedeniyle boyut üst cookie sınırı 4096 bayttan azdır. cookie Şifrelenmiş verilerin sıkıştırılması ve BREACH saldırıları gibi CRIME güvenlik sorunlarına yol açabileceğinden veriler sıkıştırılmıyor. Tabanlı TempData sağlayıcısı hakkında cookiedaha fazla bilgi için bkz CookieTempDataProvider. .

TempData sağlayıcısı seçme

TempData sağlayıcısını seçmek için dikkat edilmesi gereken birkaç nokta vardır:

  • Uygulama zaten oturum durumunu kullanıyor mu? Bu durumda TempData sağlayıcısının oturum durumunun kullanılması, uygulamanın veri boyutunu aşan ek bir maliyeti yoktur.
  • Uygulama TempData'yı yalnızca 500 bayta kadar nispeten az miktarda veri için mi kullanıyor? Bu durumda, cookie TempData sağlayıcısı TempData taşıyan her isteğe küçük bir maliyet ekler. Değilse, TempData oturum durumu sağlayıcısı TempData tüketilene kadar her istekte büyük miktarda veriyi yuvarlamaktan kaçınmak yararlı olabilir.
  • Uygulama birden çok sunucudaki bir sunucu grubunda mı çalışıyor? Bu durumda, TempData sağlayıcısını cookie Veri Koruması dışında kullanmak için ek yapılandırma gerekmez (bkz . ASP.NET Çekirdek Veri Koruması'na Genel Bakış ve Anahtar depolama sağlayıcıları).

Web tarayıcıları gibi çoğu web istemcisi, her cookie birinin boyut üst sınırına ve toplam s sayısına cookiesınırlar uygular. TempData sağlayıcısını cookie kullanırken uygulamanın bu sınırları aşmadığını doğrulayın. Verilerin toplam boyutunu göz önünde bulundurun. Şifreleme ve öbekleme nedeniyle boyut artışlarını cookie hesaba katın.

TempData sağlayıcısını yapılandırma

cookieTabanlı TempData sağlayıcısı varsayılan olarak etkindir.

Oturum tabanlı TempData sağlayıcısını etkinleştirmek için uzantı yöntemini kullanın AddSessionStateTempDataProvider . Yalnızca bir çağrı AddSessionStateTempDataProvider gereklidir:

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

Sorgu dizeleri

Sınırlı miktarda veri, yeni isteğin sorgu dizesine eklenerek bir istekten diğerine geçirilebilir. Bu, ekli duruma sahip bağlantıların e-posta veya sosyal ağlar aracılığıyla paylaşılmasını sağlayan kalıcı bir şekilde durumu yakalamak için kullanışlıdır. URL sorgu dizeleri genel olduğundan, hassas veriler için hiçbir zaman sorgu dizelerini kullanmayın.

Sorgu dizelerindeki veriler dahil olmak üzere istenmeyen paylaşıma ek olarak, uygulamayı Siteler Arası İstek Sahteciliği (CSRF) saldırılarına maruz bırakabilirsiniz. Korunan tüm oturum durumları CSRF saldırılarına karşı korunmalıdır. Daha fazla bilgi için, bkz. ASP.NET Core'da Siteler Arası İstek Sahteciliği (XSRF/CSRF) saldırılarını önleme.

Gizli alanlar

Veriler gizli form alanlarına kaydedilebilir ve sonraki istekte geri gönderilebilir. Bu, çok sayfalı formlarda yaygındır. İstemci potansiyel olarak verilerle oynanabileceğinden, uygulamanın gizli alanlarda depolanan verileri her zaman yeniden doğrulaması gerekir.

HttpContext.Items

Koleksiyon HttpContext.Items , tek bir isteği işlerken verileri depolamak için kullanılır. Bir istek işlendikten sonra koleksiyonun içeriği atılır. Koleksiyon Items genellikle bileşenlerin veya ara yazılımların bir istek sırasında farklı noktalarda çalıştıklarında iletişim kurmasına izin vermek için kullanılır ve parametreleri geçirmek için doğrudan bir yolu yoktur.

Aşağıdaki örnekte ara yazılım koleksiyona Items eklerisVerified:

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"]}");
        });
    });
}

Yalnızca tek bir uygulamada kullanılan ara yazılım için sabit string anahtarlar kabul edilebilir. Uygulamalar arasında paylaşılan ara yazılım, anahtar çakışmalarını önlemek için benzersiz nesne anahtarları kullanmalıdır. Aşağıdaki örnekte, ara yazılım sınıfında tanımlanan benzersiz bir nesne anahtarının nasıl kullanılacağı gösterilmektedir:

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

Diğer kod, ara yazılım sınıfı tarafından kullanıma sunulan anahtarı kullanarak içinde HttpContext.Items depolanan değere erişebilir:

HttpContext.Items
    .TryGetValue(HttpContextItemsMiddleware.HttpContextItemsMiddlewareKey, 
        out var middlewareSetValue);
SessionInfo_MiddlewareValue = 
    middlewareSetValue?.ToString() ?? "Middleware value not set!";

Bu yaklaşım, kodda anahtar dizelerinin kullanımını ortadan kaldırma avantajına da sahiptir.

Önbellek

Önbelleğe Alma, verileri depolamak ve almak için verimli bir yoldur. Uygulama, önbelleğe alınan öğelerin ömrünü denetleyebilir. Daha fazla bilgi için bkz . ASP.NET Core'da yanıt önbelleğe alma.

Önbelleğe alınan veriler belirli bir istek, kullanıcı veya oturumla ilişkili değildir. Diğer kullanıcı istekleri tarafından alınabilecek kullanıcıya özgü verileri önbelleğe almayın.

Uygulama genelindeki verileri önbelleğe almak için bkz . ASP.NET Core'da bellek içi önbellek.

Sık karşılaşılan hatalar

  • "'Microsoft.Extensions' türü için hizmet çözümlenemiyor. Önbelleğe Alma. 'Microsoft.AspNetCore.Session.DistributedSessionStore' etkinleştirilmeye çalışılırken Distributed.IDistributedCache'.

    Bunun nedeni genellikle en az bir IDistributedCache uygulamanın yapılandırılmamış olmasıdır. Daha fazla bilgi için bkz . ASP.NET Core'da dağıtılmış önbelleğe alma ve ASP.NET Core'da bellek içi önbellek.

Oturum ara yazılımı bir oturumu kalıcı hale getirmek için başarısız olursa:

  • Ara yazılım özel durumu günlüğe kaydeder ve istek normal şekilde devam eder.
  • Bu, öngörülemeyen davranışlara yol açar.

Yedekleme deposu kullanılamıyorsa oturum ara yazılımı oturumu kalıcı hale getiremez. Örneğin, bir kullanıcı alışveriş sepetini oturumda depolar. Kullanıcı sepete bir öğe ekler, ancak işleme başarısız olur. Uygulama hatadan haberdar olmadığından, kullanıcıya öğenin sepetine eklendiğini bildirir ve bu doğru değildir.

Hataları denetlemek için önerilen yaklaşım, uygulama oturuma yazmayı bitirdiğinde çağrısı await feature.Session.CommitAsync yapmaktır. CommitAsync , yedekleme deposu kullanılamıyorsa bir özel durum oluşturur. Başarısız olursa CommitAsync , uygulama özel durumu işleyebilir. LoadAsync veri deposu kullanılamadığında aynı koşullar altında atar.

Ek kaynaklar

Web grubunda ASP.NET Core barındırma