Správa relací a stavu v ASP.NET Core
Rick Anderson, Kirk Larkin a Diana LaRose
HTTP je bezstavový protokol. Ve výchozím nastavení jsou požadavky HTTP nezávislé zprávy, které nezachovají uživatelské hodnoty. Tento článek popisuje několik přístupů k zachování uživatelských dat mezi požadavky.
Pokyny Blazor ke správě stavu, které přidávají nebo nahrazují pokyny v tomto článku, najdete v tématu ASP.NET správě stavu jádraBlazor.
Správa stavu
Stav lze uložit pomocí několika přístupů. Každý přístup je popsaný dále v tomto článku.
Přístup k úložišti | Mechanismus úložiště |
---|---|
Koláčky | Soubory cookie HTTP. Může obsahovat data uložená pomocí kódu aplikace na straně serveru. |
Stav relace | Soubory cookie HTTP a kód aplikace na straně serveru |
TempData | Soubory cookie HTTP nebo stav relace |
Řetězce dotazů | Řetězce dotazů HTTP |
Skrytá pole | Pole formuláře HTTP |
HttpContext.Items | Kód aplikace na straně serveru |
Cache | Kód aplikace na straně serveru |
SignalR/Blazor Server a správa stavu na základě kontextu HTTP
SignalR aplikace by neměly používat stav relace a další přístupy ke správě stavu, které při ukládání informací spoléhají na stabilní kontext HTTP. SignalR aplikace můžou ukládat stav jednotlivých připojení v Context.Items
centru. Další informace a alternativní přístupy ke správě stavu pro Blazor Server aplikace najdete v tématu ASP.NET Blazor Základní správa stavu.
Soubory cookie
Soubory cookie ukládají data napříč požadavky. Vzhledem k tomu, že se soubory cookie odesílají s každou žádostí, měla by být jejich velikost zachována na minimum. V ideálním případě by měl být uložen cookie pouze identifikátor s daty uloženými aplikací. Většina prohlížečů omezuje cookie velikost na 4096 bajtů. Pro každou doménu je k dispozici pouze omezený počet souborů cookie.
Protože soubory cookie podléhají manipulaci, musí je aplikace ověřit. Soubory cookie můžou odstranit uživatelé a jejich platnost vyprší. Soubory cookie jsou však obecně nejodolnější formou trvalosti dat na klientovi.
Soubory cookie se často používají k přizpůsobení, kde je obsah přizpůsobený známému uživateli. Uživatel je identifikován pouze a ve většině případů se neověřuje. Může cookie uložit jméno uživatele, název účtu nebo jedinečné ID uživatele, například IDENTIFIKÁTOR GUID. Dá cookie se použít pro přístup k individuálnímu nastavení uživatele, jako je například upřednostňovaná barva pozadí webu.
Při vydávání souborů cookie a řešení privacy problémů se podívejte na obecné nařízení Evropské unie o ochraně osobních údajů (GDPR). Další informace najdete v tématu Obecná podpora nařízení o ochraně osobních údajů (GDPR) v ASP.NET Core.
Stav relace
Stav relace je scénář ASP.NET Core pro ukládání uživatelských dat, zatímco uživatel prochází webovou aplikaci. Stav relace používá úložiště spravované aplikací k zachování dat napříč požadavky z klienta. Data relace jsou podporována mezipamětí a považují se za dočasné data. Web by měl dál fungovat bez dat relace. Důležitá data aplikace by měla být uložená v uživatelské databázi a uložená v mezipaměti v relaci pouze jako optimalizace výkonu.
Relace není v SignalR aplikacích podporovaná, protože SignalR centrum může spouštět nezávisle na kontextu HTTP. K tomu může dojít například v případě, že je dlouhý požadavek na dotazování otevřený centrem nad rámec životnosti kontextu HTTP požadavku.
ASP.NET Core udržuje stav relace poskytnutím cookie klientovi, který obsahuje ID relace. cookie ID relace:
- Odešle se do aplikace s každou žádostí.
- Aplikace je používána k načtení dat relace.
Stav relace vykazuje následující chování:
- Relace cookie je specifická pro prohlížeč. Relace se nesdílejí napříč prohlížeči.
- Soubory cookie relace se odstraní, když relace prohlížeče skončí.
- cookie Pokud je přijata pro relaci s vypršenou platností, vytvoří se nová relace, která používá stejnou relaci cookie.
- Prázdné relace se nezachovají. Relace musí mít nastavenou alespoň jednu hodnotu, aby se relace zachovala napříč požadavky. Pokud se relace nezachová, vygeneruje se nové ID relace pro každý nový požadavek.
- Aplikace uchovává relaci po omezenou dobu po poslední žádosti. Aplikace buď nastaví časový limit relace, nebo použije výchozí hodnotu 20 minut. Stav relace je ideální pro ukládání uživatelských dat:
- To je specifické pro konkrétní relaci.
- Pokud data nevyžadují trvalé úložiště napříč relacemi.
- Data relace se odstraní buď při ISession.Clear zavolání implementace, nebo při vypršení platnosti relace.
- Neexistuje žádný výchozí mechanismus, který by informoval kód aplikace, že byl klientský prohlížeč zavřený nebo když je relace cookie odstraněna nebo vypršela jeho platnost.
- Soubory cookie stavu relace nejsou ve výchozím nastavení označené jako nezbytné. Stav relace není funkční, pokud není sledování povoleno návštěvníkem webu. Další informace najdete v tématu Obecná podpora nařízení o ochraně osobních údajů (GDPR) v ASP.NET Core.
- Poznámka: Funkce relace bez souborů cookie z rozhraní ASP.NET Framework není nahrazena, protože je považována za nezabezpečenou a může vést k útokům na opravu relací.
Upozorňující
Neukládejte citlivá data ve stavu relace. Uživatel nemusí zavřít prohlížeč a vymazat relaci cookie. Některé prohlížeče udržují platné soubory cookie relace v oknech prohlížeče. Relace nemusí být omezena na jednoho uživatele. Další uživatel může pokračovat v procházení aplikace se stejnou relací cookie.
Zprostředkovatel mezipaměti v paměti ukládá data relace do paměti serveru, kde se nachází aplikace. Ve scénáři serverové farmy:
- Pomocí rychlých relací můžete každou relaci svázat s konkrétní instancí aplikace na jednotlivém serveru. Aplikace Azure Služba používá směrování žádostí aplikace (ARR) k vynucování rychlých relací ve výchozím nastavení. Rychlé relace ale můžou ovlivnit škálovatelnost a komplikují aktualizace webových aplikací. Lepším přístupem je použít distribuovanou mezipaměť Redis nebo SQL Server, která nevyžaduje rychlé relace. Další informace naleznete v tématu Distribuované ukládání do mezipaměti v ASP.NET Core.
- Relace cookie je šifrovaná prostřednictvím IDataProtector. Ochrana dat musí být správně nakonfigurovaná tak, aby na každém počítači četla soubory cookie relace. Další informace najdete v tématu ASP.NET Přehled základní ochrany dat a poskytovatelé úložiště klíčů.
Konfigurace stavu relace
Middleware pro správu stavu relace je součástí architektury. Pokud chcete povolit middleware relace, Program.cs
musí obsahovat:
- Každá z mezipamětí IDistributedCache paměti. Implementace
IDistributedCache
se používá jako záložní úložiště pro relaci. Další informace naleznete v tématu Distribuované ukládání do mezipaměti v ASP.NET Core. - Volání AddSession
- Volání UseSession
Následující kód ukazuje, jak nastavit zprostředkovatele relace v paměti s výchozí implementací IDistributedCache
v paměti:
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();
Předchozí kód nastaví krátký časový limit pro zjednodušení testování.
Pořadí middlewaru je důležité. Zavolat UseSession
po UseRouting
a před MapRazorPages
a MapDefaultControllerRoute
. Viz Řazení middlewaru.
HttpContext.Session je k dispozici po nakonfigurování stavu relace.
HttpContext.Session
není možné získat přístup před UseSession
zavolání.
Po zahájení zápisu aplikace do streamu odpovědí nejde vytvořit novou relaci s novou relací cookie . Výjimka se zaznamená v protokolu webového serveru a nezobrazí se v prohlížeči.
Asynchronní načtení stavu relace
Výchozí zprostředkovatel relace v ASP.NET Core načte záznamy relace ze základního IDistributedCache záložního úložiště asynchronně pouze v případě, že ISession.LoadAsync metoda je explicitně volána před TryGetValue, Setnebo Remove metody. Pokud LoadAsync
není volána jako první, základní záznam relace se načte synchronně, což může mít za následek snížení výkonu ve velkém měřítku.
Chcete-li, aby aplikace vynucovaly tento vzor, zabalte DistributedSessionStore a DistributedSession implementace s verzemi, které vyvolá výjimku, pokud LoadAsync
metoda není volána před TryGetValue
, Set
nebo Remove
. Zaregistrujte zabalené verze v kontejneru služeb.
Možnosti relace
Chcete-li přepsat výchozí hodnoty relace, použijte SessionOptions.
Možnost | Popis |
---|---|
Cookie | Určuje nastavení použitá k vytvoření cookiesouboru . Name výchozí hodnota je SessionDefaults.CookieName (.AspNetCore.Session ). Path výchozí hodnota je SessionDefaults.CookiePath (/ ). SameSite výchozí hodnota je SameSiteMode.Lax (1 ). Výchozí hodnotou HttpOnly je true . Výchozí hodnotou IsEssential je false . |
IdleTimeout | Určuje IdleTimeout , jak dlouho může být relace nečinná, než se její obsah opustí. Každý přístup k relaci resetuje časový limit. Toto nastavení se vztahuje pouze na obsah relace, nikoli na cookie. Výchozí nastavení je 20 minut. |
IOTimeout | Maximální doba, po kterou je možné načíst relaci z úložiště nebo ji potvrdit zpět do úložiště. Toto nastavení se může vztahovat pouze na asynchronní operace. Tento časový limit lze zakázat pomocí InfiniteTimeSpan. Výchozí hodnota je 1 minuta. |
Relace používá cookie ke sledování a identifikaci požadavků z jednoho prohlížeče. Ve výchozím nastavení se tento cookie název .AspNetCore.Session
používá a používá cestu /
. cookie Vzhledem k tomu, že výchozí nastavení neurčuje doménu, není pro skript na straně klienta na stránce k dispozici (protože HttpOnly výchozí hodnota je true
).
Chcete-li přepsat cookie výchozí hodnoty relace, použijte 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();
Aplikace pomocí IdleTimeout vlastnosti určuje, jak dlouho může být relace nečinná, než se její obsah v mezipaměti serveru opustí. Tato vlastnost je nezávislá na cookie vypršení platnosti. Každý požadavek, který prochází middlewarem relace, resetuje časový limit.
Stav relace není uzamčený. Pokud se dva požadavky současně pokusí upravit obsah relace, poslední požadavek přepíše první. Session
je implementováno jako koherentní relace, což znamená, že veškerý obsah je uložen společně. Když se dva požadavky snaží upravit různé hodnoty relace, může poslední požadavek přepsat změny relace provedené prvním.
Nastavení a získání hodnot relace
Stav relace je přístupný z Razor třídy Pages PageModel nebo třídy MVC Controller s HttpContext.Session. Tato vlastnost je ISession implementace.
Implementace ISession
poskytuje několik rozšiřujících metod pro nastavení a načtení celočíselné a řetězcové hodnoty. Metody rozšíření jsou v Microsoft.AspNetCore.Http oboru názvů.
ISession
rozšiřující metody:
- Get(ISession; String)
- GetInt32(ISession; String)
- GetString(ISession; String)
- SetInt32(ISession, String, Int32)
- SetString(ISession, String, String)
Následující příklad načte hodnotu relace pro IndexModel.SessionKeyName
klíč (_Name
v ukázkové aplikaci) na Razor stránce Pages:
@page
@using Microsoft.AspNetCore.Http
@model IndexModel
...
Name: @HttpContext.Session.GetString(IndexModel.SessionKeyName)
Následující příklad ukazuje, jak nastavit a získat celé číslo a řetězec:
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);
}
}
Následující kód zobrazí hodnoty relace na Razor stránce:
@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>
Všechna data relace musí být serializována, aby bylo možné povolit scénář distribuované mezipaměti, i když používáte mezipaměť v paměti. Řetězcové a celočíselné serializátory jsou poskytovány rozšiřujícími metodami ISession. Komplexní typy musí být serializovány uživatelem pomocí jiného mechanismu, například JSON.
K serializaciobjektůch
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);
}
}
Následující příklad ukazuje, jak nastavit a získat serializovatelný objekt s SessionExtensions
třídou:
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));
}
}
}
Upozorňující
Uložení živého objektu v relaci by se mělo používat s opatrností, protože u serializovaných objektů může dojít k mnoha problémům. Další informace najdete v tématu Relace, které by měly umožňovat ukládání objektů (dotnet/aspnetcore #18159).
TempData
ASP.NET Core zpřístupňuje stránky tempdata nebo kontroleru TempData.Razor Tato vlastnost ukládá data, dokud se nepřečte v jiném požadavku. Metody Keep(String) a Peek(string) lze použít k prozkoumání dat bez odstranění na konci požadavku. Zachovejte značky všech položek ve slovníku pro uchovávání informací. TempData
je:
- Užitečné pro přesměrování v případě, že se data vyžadují pro více než jeden požadavek.
- Implementují
TempData
poskytovatelé pomocí souborů cookie nebo stavu relace.
Ukázky tempData
Představte si následující stránku, která vytvoří zákazníka:
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");
}
}
Zobrazí se následující stránka TempData["Message"]
:
@page
@model IndexModel
<h1>Peek Contacts</h1>
@{
if (TempData.Peek("Message") != null)
{
<h3>Message: @TempData.Peek("Message")</h3>
}
}
@*Content removed for brevity.*@
V předchozím kódu se na konci požadavku neodstraní, TempData["Message"]
protože Peek
se používá. Při aktualizaci stránky se zobrazí obsah souboru TempData["Message"]
.
Následující kód je podobný předchozímu kódu, ale používá Keep
se k zachování dat na konci požadavku:
@page
@model IndexModel
<h1>Contacts Keep</h1>
@{
if (TempData["Message"] != null)
{
<h3>Message: @TempData["Message"]</h3>
}
TempData.Keep("Message");
}
@*Content removed for brevity.*@
Přechod mezi stránkami IndexPeek a IndexKeep se neodstraní TempData["Message"]
.
Následující kód se zobrazí TempData["Message"]
, ale na konci požadavku TempData["Message"]
se odstraní:
@page
@model IndexModel
<h1>Index no Keep or Peek</h1>
@{
if (TempData["Message"] != null)
{
<h3>Message: @TempData["Message"]</h3>
}
}
@*Content removed for brevity.*@
Zprostředkovatelé tempData
Ve cookievýchozím nastavení se k ukládání tempData do souborů cookie používá zprostředkovatel TempData založený na databázi TempData.
Data cookie se šifrují pomocí IDataProtectorzakódovaných Base64UrlTextEncoderdat a potom se zakódují. Maximální cookie velikost je menší než 4096 bajtů kvůli šifrování a bloků dat. Data cookie nejsou komprimovaná, protože komprese šifrovaných dat může vést k problémům se zabezpečením, jako jsou útoky CRIME a BREACH útoky. Další informace o poskytovateli tempdata založeném cookiena technologii TempData naleznete v tématu CookieTempDataProvider.
Volba zprostředkovatele TempData
Volba zprostředkovatele TempData zahrnuje několik aspektů, například:
- Používá aplikace už stav relace? Pokud ano, použití poskytovatele TempData stavu relace nemá žádné další náklady na aplikaci nad rámec velikosti dat.
- Používá aplikace tempData jen střídmě pro relativně malé objemy dat, až 500 bajtů? Pokud ano, cookie poskytovatel TempData přidá malé náklady na každý požadavek, který nese TempData. Pokud tomu tak není, může být poskytovatel tempData stavu relace výhodný, aby se zabránilo zaokrouhlení velkého množství dat v každém požadavku, dokud se tempData nespotřebuje.
- Běží aplikace v serverové farmě na více serverech? Pokud ano, není nutná žádná další konfigurace pro použití cookie zprostředkovatele TempData mimo ochranu dat. Další informace najdete v tématu ASP.NET Přehled základní ochrany dat a poskytovatelé úložiště klíčů.
Většina webových klientů, jako jsou webové prohlížeče, vynucuje omezení maximální velikosti každého cookie a celkového počtu souborů cookie. Při použití cookie zprostředkovatele TempData ověřte, že aplikace tyto limity nepřekročí. Zvažte celkovou velikost dat. Účet se zvětší cookie kvůli šifrování a bloků dat.
Konfigurace zprostředkovatele TempData
Poskytovatel cookieTempData založený na technologii TempData je ve výchozím nastavení povolený.
Pokud chcete povolit zprostředkovatele TempData založeného na relaci, použijte metodu AddSessionStateTempDataProvider rozšíření. Vyžaduje se AddSessionStateTempDataProvider
pouze jedno volání:
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();
Řetězce dotazů
Omezené množství dat je možné předat z jednoho požadavku do jiného přidáním do řetězce dotazu nového požadavku. To je užitečné pro trvalé zachycení stavu, které umožňuje sdílení propojení s vloženým stavem prostřednictvím e-mailu nebo sociálních sítí. Protože řetězce dotazu ADRESY URL jsou veřejné, nikdy nepoužívejte řetězce dotazů pro citlivá data.
Kromě nezamýšleného sdílení, včetně dat v řetězcích dotazů, může aplikace vystavit útokům CSRF (Cross-Site Request Forgery). Všechny zachované stavy relace musí chránit před útoky CSRF. Další informace najdete v tématu Prevence útoků založených na padělání žádosti posílané mezi weby (XSRF/CSRF) v ASP.NET Core.
Skrytá pole
Data lze uložit do skrytých polí formuláře a publikovat zpět na další požadavek. To je běžné ve vícestrákových formulářích. Vzhledem k tomu, že klient může potenciálně manipulovat s daty, musí aplikace vždy znovu obnovit data uložená ve skrytých polích.
HttpContext.Items
Kolekce HttpContext.Items se používá k ukládání dat při zpracování jednoho požadavku. Obsah kolekce se po zpracování požadavku zahodí. Kolekce Items
se často používá k tomu, aby komponenty nebo middleware komunikovaly, když během požadavku pracují v různých bodech v čase a nemají přímý způsob předávání parametrů.
V následujícím příkladu middleware přidá isVerified
do Items
kolekce:
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();
U middlewaru, který se používá jenom v jedné aplikaci, je nepravděpodobné, že použití pevného string
klíče způsobí kolizi klíče. Aby se však zabránilo úplné kolizi klíče, object
lze ji použít jako klíč položky. Tento přístup je zvláště užitečný pro middleware, který se sdílí mezi aplikacemi, a má také výhodu odstranění použití klíčových řetězců v kódu. Následující příklad ukazuje, jak použít object
klíč definovaný v middlewarové třídě:
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>();
}
}
Jiný kód má přístup k hodnotě uložené v HttpContext.Items
klíči vystavené middlewarovou třídou:
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!");
}
}
Mezipaměť
Ukládání do mezipaměti je efektivní způsob, jak ukládat a načítat data. Aplikace může řídit životnost položek uložených v mezipaměti. Další informace najdete v tématu Ukládání odpovědí do mezipaměti v ASP.NET Core.
Data uložená v mezipaměti nejsou přidružená ke konkrétnímu požadavku, uživateli nebo relaci. Neukádejte data specifická pro uživatele, která mohou být načtena jinými požadavky uživatelů.
Pokud chcete ukládat data do mezipaměti pro celou aplikaci, přečtěte si téma Mezipaměť v paměti v ASP.NET Core.
Kontrola stavu relace
ISession.IsAvailable je určen ke kontrole přechodných selhání. Volání IsAvailable
před spuštěním middlewaru relace vyvolá výjimku InvalidOperationException
.
Knihovny, které potřebují otestovat dostupnost relace, mohou používat HttpContext.Features.Get<ISessionFeature>()?.Session != null
.
Běžné chyby
"Nelze přeložit službu pro typ Microsoft.Extensions.Caching.Distributed.IDistributedCache při pokusu o aktivaci Microsoft.AspNetCore.Session.DistributedSessionStore."
Příčinou je obvykle selhání konfigurace aspoň jedné
IDistributedCache
implementace. Další informace najdete v tématu Distribuované ukládání do mezipaměti v ASP.NET Core a mezipaměti v paměti v ASP.NET Core.
Pokud se middleware relace nepodaří zachovat relaci:
- Middleware zaznamená výjimku a požadavek pokračuje normálně.
- To vede k nepředvídatelným chováním.
Middleware relace nemůže zachovat relaci, pokud záložní úložiště není k dispozici. Uživatel například ukládá nákupní košík v relaci. Uživatel přidá položku do košíku, ale potvrzení se nezdaří. Aplikace o chybě neví, takže hlásí uživateli, že byla položka přidána do košíku, což není pravda.
Doporučeným přístupem ke kontrole chyb je volání await feature.Session.CommitAsync
při zápisu aplikace do relace. CommitAsync vyvolá výjimku, pokud záložní úložiště není k dispozici. Pokud CommitAsync
selže, aplikace může výjimku zpracovat. LoadAsync vyvolá za stejných podmínek, pokud úložiště dat není k dispozici.
Další materiály
Rick Anderson, Kirk Larkin a Diana LaRose
HTTP je bezstavový protokol. Ve výchozím nastavení jsou požadavky HTTP nezávislé zprávy, které nezachovají uživatelské hodnoty. Tento článek popisuje několik přístupů k zachování uživatelských dat mezi požadavky.
Zobrazení nebo stažení ukázkového kódu (postup stažení)
Správa stavu
Stav lze uložit pomocí několika přístupů. Každý přístup je popsaný dále v tomto článku.
Přístup k úložišti | Mechanismus úložiště |
---|---|
Koláčky | Soubory cookie HTTP. Může obsahovat data uložená pomocí kódu aplikace na straně serveru. |
Stav relace | Soubory cookie HTTP a kód aplikace na straně serveru |
TempData | Soubory cookie HTTP nebo stav relace |
Řetězce dotazů | Řetězce dotazů HTTP |
Skrytá pole | Pole formuláře HTTP |
HttpContext.Items | Kód aplikace na straně serveru |
Cache | Kód aplikace na straně serveru |
SignalR/Blazor Server a správa stavu na základě kontextu HTTP
SignalR aplikace by neměly používat stav relace a další přístupy ke správě stavu, které při ukládání informací spoléhají na stabilní kontext HTTP. SignalR aplikace můžou ukládat stav jednotlivých připojení v Context.Items
centru. Další informace a alternativní přístupy ke správě stavu pro Blazor Server aplikace najdete v tématu ASP.NET Blazor Základní správa stavu.
Soubory cookie
Soubory cookie ukládají data napříč požadavky. Vzhledem k tomu, že se soubory cookie odesílají s každou žádostí, měla by být jejich velikost zachována na minimum. V ideálním případě by měl být uložen cookie pouze identifikátor s daty uloženými aplikací. Většina prohlížečů omezuje cookie velikost na 4096 bajtů. Pro každou doménu je k dispozici pouze omezený počet souborů cookie.
Protože soubory cookie podléhají manipulaci, musí je aplikace ověřit. Soubory cookie můžou odstranit uživatelé a jejich platnost vyprší. Soubory cookie jsou však obecně nejodolnější formou trvalosti dat na klientovi.
Soubory cookie se často používají k přizpůsobení, kde je obsah přizpůsobený známému uživateli. Uživatel je identifikován pouze a ve většině případů se neověřuje. Může cookie uložit jméno uživatele, název účtu nebo jedinečné ID uživatele, například IDENTIFIKÁTOR GUID. Dá cookie se použít pro přístup k individuálnímu nastavení uživatele, jako je například upřednostňovaná barva pozadí webu.
Při vydávání souborů cookie a řešení privacy problémů se podívejte na obecné nařízení Evropské unie o ochraně osobních údajů (GDPR). Další informace najdete v tématu Obecná podpora nařízení o ochraně osobních údajů (GDPR) v ASP.NET Core.
Stav relace
Stav relace je scénář ASP.NET Core pro ukládání uživatelských dat, zatímco uživatel prochází webovou aplikaci. Stav relace používá úložiště spravované aplikací k zachování dat napříč požadavky z klienta. Data relace jsou podporována mezipamětí a považují se za dočasné data. Web by měl dál fungovat bez dat relace. Důležitá data aplikace by měla být uložená v uživatelské databázi a uložená v mezipaměti v relaci pouze jako optimalizace výkonu.
Relace není v SignalR aplikacích podporovaná, protože SignalR centrum může spouštět nezávisle na kontextu HTTP. K tomu může dojít například v případě, že je dlouhý požadavek na dotazování otevřený centrem nad rámec životnosti kontextu HTTP požadavku.
ASP.NET Core udržuje stav relace poskytnutím cookie klientovi, který obsahuje ID relace. cookie ID relace:
- Odešle se do aplikace s každou žádostí.
- Aplikace je používána k načtení dat relace.
Stav relace vykazuje následující chování:
- Relace cookie je specifická pro prohlížeč. Relace se nesdílejí napříč prohlížeči.
- Soubory cookie relace se odstraní, když relace prohlížeče skončí.
- cookie Pokud je přijata pro relaci s vypršenou platností, vytvoří se nová relace, která používá stejnou relaci cookie.
- Prázdné relace se nezachovají. Relace musí mít nastavenou alespoň jednu hodnotu, aby se relace zachovala napříč požadavky. Pokud se relace nezachová, vygeneruje se nové ID relace pro každý nový požadavek.
- Aplikace uchovává relaci po omezenou dobu po poslední žádosti. Aplikace buď nastaví časový limit relace, nebo použije výchozí hodnotu 20 minut. Stav relace je ideální pro ukládání uživatelských dat:
- To je specifické pro konkrétní relaci.
- Pokud data nevyžadují trvalé úložiště napříč relacemi.
- Data relace se odstraní buď při ISession.Clear zavolání implementace, nebo při vypršení platnosti relace.
- Neexistuje žádný výchozí mechanismus, který by informoval kód aplikace, že byl klientský prohlížeč zavřený nebo když je relace cookie odstraněna nebo vypršela jeho platnost.
- Soubory cookie stavu relace nejsou ve výchozím nastavení označené jako nezbytné. Stav relace není funkční, pokud není sledování povoleno návštěvníkem webu. Další informace najdete v tématu Obecná podpora nařízení o ochraně osobních údajů (GDPR) v ASP.NET Core.
Upozorňující
Neukládejte citlivá data ve stavu relace. Uživatel nemusí zavřít prohlížeč a vymazat relaci cookie. Některé prohlížeče udržují platné soubory cookie relace v oknech prohlížeče. Relace nemusí být omezena na jednoho uživatele. Další uživatel může pokračovat v procházení aplikace se stejnou relací cookie.
Zprostředkovatel mezipaměti v paměti ukládá data relace do paměti serveru, kde se nachází aplikace. Ve scénáři serverové farmy:
- Pomocí rychlých relací můžete každou relaci svázat s konkrétní instancí aplikace na jednotlivém serveru. Aplikace Azure Služba používá směrování žádostí aplikace (ARR) k vynucování rychlých relací ve výchozím nastavení. Rychlé relace ale můžou ovlivnit škálovatelnost a komplikují aktualizace webových aplikací. Lepším přístupem je použít distribuovanou mezipaměť Redis nebo SQL Server, která nevyžaduje rychlé relace. Další informace naleznete v tématu Distribuované ukládání do mezipaměti v ASP.NET Core.
- Relace cookie je šifrovaná prostřednictvím IDataProtector. Ochrana dat musí být správně nakonfigurovaná tak, aby na každém počítači četla soubory cookie relace. Další informace najdete v tématu ASP.NET Přehled základní ochrany dat a poskytovatelé úložiště klíčů.
Konfigurace stavu relace
Balíček Microsoft.AspNetCore.Session :
- Architektura je zahrnuta implicitně.
- Poskytuje middleware pro správu stavu relace.
Pokud chcete povolit middleware relace, Startup
musí obsahovat:
- Každá z mezipamětí IDistributedCache paměti. Implementace
IDistributedCache
se používá jako záložní úložiště pro relaci. Další informace naleznete v tématu Distribuované ukládání do mezipaměti v ASP.NET Core. - Volání do AddSession
ConfigureServices
. - Volání do UseSession
Configure
.
Následující kód ukazuje, jak nastavit zprostředkovatele relace v paměti s výchozí implementací IDistributedCache
v paměti:
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();
});
}
}
Předchozí kód nastaví krátký časový limit pro zjednodušení testování.
Pořadí middlewaru je důležité. Zavolat UseSession
po UseRouting
a před UseEndpoints
. Viz Řazení middlewaru.
HttpContext.Session je k dispozici po nakonfigurování stavu relace.
HttpContext.Session
není možné získat přístup před UseSession
zavolání.
Po zahájení zápisu aplikace do streamu odpovědí nejde vytvořit novou relaci s novou relací cookie . Výjimka se zaznamená v protokolu webového serveru a nezobrazí se v prohlížeči.
Asynchronní načtení stavu relace
Výchozí zprostředkovatel relace v ASP.NET Core načte záznamy relace ze základního IDistributedCache záložního úložiště asynchronně pouze v případě, že ISession.LoadAsync metoda je explicitně volána před TryGetValue, Setnebo Remove metody. Pokud LoadAsync
není volána jako první, základní záznam relace se načte synchronně, což může mít za následek snížení výkonu ve velkém měřítku.
Chcete-li, aby aplikace vynucovaly tento vzor, zabalte DistributedSessionStore a DistributedSession implementace s verzemi, které vyvolá výjimku, pokud LoadAsync
metoda není volána před TryGetValue
, Set
nebo Remove
. Zaregistrujte zabalené verze v kontejneru služeb.
Možnosti relace
Chcete-li přepsat výchozí hodnoty relace, použijte SessionOptions.
Možnost | Popis |
---|---|
Cookie | Určuje nastavení použitá k vytvoření cookiesouboru . Name výchozí hodnota je SessionDefaults.CookieName (.AspNetCore.Session ). Path výchozí hodnota je SessionDefaults.CookiePath (/ ). SameSite výchozí hodnota je SameSiteMode.Lax (1 ). Výchozí hodnotou HttpOnly je true . Výchozí hodnotou IsEssential je false . |
IdleTimeout | Určuje IdleTimeout , jak dlouho může být relace nečinná, než se její obsah opustí. Každý přístup k relaci resetuje časový limit. Toto nastavení se vztahuje pouze na obsah relace, nikoli na cookie. Výchozí nastavení je 20 minut. |
IOTimeout | Maximální doba, po kterou je možné načíst relaci z úložiště nebo ji potvrdit zpět do úložiště. Toto nastavení se může vztahovat pouze na asynchronní operace. Tento časový limit lze zakázat pomocí InfiniteTimeSpan. Výchozí hodnota je 1 minuta. |
Relace používá cookie ke sledování a identifikaci požadavků z jednoho prohlížeče. Ve výchozím nastavení se tento cookie název .AspNetCore.Session
používá a používá cestu /
. cookie Vzhledem k tomu, že výchozí nastavení neurčuje doménu, není pro skript na straně klienta na stránce k dispozici (protože HttpOnly výchozí hodnota je true
).
Chcete-li přepsat cookie výchozí hodnoty relace, použijte 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();
}
Aplikace pomocí IdleTimeout vlastnosti určuje, jak dlouho může být relace nečinná, než se její obsah v mezipaměti serveru opustí. Tato vlastnost je nezávislá na cookie vypršení platnosti. Každý požadavek, který prochází middlewarem relace, resetuje časový limit.
Stav relace není uzamčený. Pokud se dva požadavky současně pokusí upravit obsah relace, poslední požadavek přepíše první. Session
je implementováno jako koherentní relace, což znamená, že veškerý obsah je uložen společně. Když se dva požadavky snaží upravit různé hodnoty relace, může poslední požadavek přepsat změny relace provedené prvním.
Nastavení a získání hodnot relace
Stav relace je přístupný z Razor třídy Pages PageModel nebo třídy MVC Controller s HttpContext.Session. Tato vlastnost je ISession implementace.
Implementace ISession
poskytuje několik rozšiřujících metod pro nastavení a načtení celočíselné a řetězcové hodnoty. Metody rozšíření jsou v Microsoft.AspNetCore.Http oboru názvů.
ISession
rozšiřující metody:
- Get(ISession; String)
- GetInt32(ISession; String)
- GetString(ISession; String)
- SetInt32(ISession, String, Int32)
- SetString(ISession, String, String)
Následující příklad načte hodnotu relace pro IndexModel.SessionKeyName
klíč (_Name
v ukázkové aplikaci) na Razor stránce Pages:
@page
@using Microsoft.AspNetCore.Http
@model IndexModel
...
Name: @HttpContext.Session.GetString(IndexModel.SessionKeyName)
Následující příklad ukazuje, jak nastavit a získat celé číslo a řetězec:
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);
Všechna data relace musí být serializována, aby bylo možné povolit scénář distribuované mezipaměti, i když používáte mezipaměť v paměti. Řetězcové a celočíselné serializátory jsou poskytovány rozšiřujícími metodami ISession. Komplexní typy musí být serializovány uživatelem pomocí jiného mechanismu, například JSON.
K serializaciobjektůch
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);
}
}
Následující příklad ukazuje, jak nastavit a získat serializovatelný objekt s SessionExtensions
třídou:
// Requires SessionExtensions from sample download.
if (HttpContext.Session.Get<DateTime>(SessionKeyTime) == default)
{
HttpContext.Session.Set<DateTime>(SessionKeyTime, currentTime);
}
TempData
ASP.NET Core zpřístupňuje stránky tempdata nebo kontroleru TempData.Razor Tato vlastnost ukládá data, dokud se nepřečte v jiném požadavku. Metody Keep(String) a Peek(string) lze použít k prozkoumání dat bez odstranění na konci požadavku. Zachovejte značky všech položek ve slovníku pro uchovávání informací. TempData
je:
- Užitečné pro přesměrování v případě, že se data vyžadují pro více než jeden požadavek.
- Implementují
TempData
poskytovatelé pomocí souborů cookie nebo stavu relace.
Ukázky tempData
Představte si následující stránku, která vytvoří zákazníka:
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");
}
}
Zobrazí se následující stránka TempData["Message"]
:
@page
@model IndexModel
<h1>Peek Contacts</h1>
@{
if (TempData.Peek("Message") != null)
{
<h3>Message: @TempData.Peek("Message")</h3>
}
}
@*Content removed for brevity.*@
V předchozím kódu se na konci požadavku neodstraní, TempData["Message"]
protože Peek
se používá. Při aktualizaci stránky se zobrazí obsah souboru TempData["Message"]
.
Následující kód je podobný předchozímu kódu, ale používá Keep
se k zachování dat na konci požadavku:
@page
@model IndexModel
<h1>Contacts Keep</h1>
@{
if (TempData["Message"] != null)
{
<h3>Message: @TempData["Message"]</h3>
}
TempData.Keep("Message");
}
@*Content removed for brevity.*@
Přechod mezi stránkami IndexPeek a IndexKeep se neodstraní TempData["Message"]
.
Následující kód se zobrazí TempData["Message"]
, ale na konci požadavku TempData["Message"]
se odstraní:
@page
@model IndexModel
<h1>Index no Keep or Peek</h1>
@{
if (TempData["Message"] != null)
{
<h3>Message: @TempData["Message"]</h3>
}
}
@*Content removed for brevity.*@
Zprostředkovatelé tempData
Ve cookievýchozím nastavení se k ukládání tempData do souborů cookie používá zprostředkovatel TempData založený na databázi TempData.
Data cookie se šifrují pomocí IDataProtectorzakódovaných Base64UrlTextEncoderdat a potom se zakódují. Maximální cookie velikost je menší než 4096 bajtů kvůli šifrování a bloků dat. Data cookie nejsou komprimovaná, protože komprese šifrovaných dat může vést k problémům se zabezpečením, jako jsou útoky CRIME a BREACH útoky. Další informace o poskytovateli tempdata založeném cookiena technologii TempData naleznete v tématu CookieTempDataProvider.
Volba zprostředkovatele TempData
Volba zprostředkovatele TempData zahrnuje několik aspektů, například:
- Používá aplikace už stav relace? Pokud ano, použití poskytovatele TempData stavu relace nemá žádné další náklady na aplikaci nad rámec velikosti dat.
- Používá aplikace tempData jen střídmě pro relativně malé objemy dat, až 500 bajtů? Pokud ano, cookie poskytovatel TempData přidá malé náklady na každý požadavek, který nese TempData. Pokud tomu tak není, může být poskytovatel tempData stavu relace výhodný, aby se zabránilo zaokrouhlení velkého množství dat v každém požadavku, dokud se tempData nespotřebuje.
- Běží aplikace v serverové farmě na více serverech? Pokud ano, není nutná žádná další konfigurace pro použití cookie zprostředkovatele TempData mimo ochranu dat (viz ASP.NET Přehled základní ochrany dat a poskytovatelé úložiště klíčů).
Většina webových klientů, jako jsou webové prohlížeče, vynucuje omezení maximální velikosti každého cookie a celkového počtu souborů cookie. Při použití cookie zprostředkovatele TempData ověřte, že aplikace tyto limity nepřekročí. Zvažte celkovou velikost dat. Účet se zvětší cookie kvůli šifrování a bloků dat.
Konfigurace zprostředkovatele TempData
Poskytovatel cookieTempData založený na technologii TempData je ve výchozím nastavení povolený.
Pokud chcete povolit zprostředkovatele TempData založeného na relaci, použijte metodu AddSessionStateTempDataProvider rozšíření. Vyžaduje se AddSessionStateTempDataProvider
pouze jedno volání:
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();
});
}
Řetězce dotazů
Omezené množství dat je možné předat z jednoho požadavku do jiného přidáním do řetězce dotazu nového požadavku. To je užitečné pro trvalé zachycení stavu, které umožňuje sdílení propojení s vloženým stavem prostřednictvím e-mailu nebo sociálních sítí. Protože řetězce dotazu ADRESY URL jsou veřejné, nikdy nepoužívejte řetězce dotazů pro citlivá data.
Kromě nezamýšleného sdílení, včetně dat v řetězcích dotazů, může aplikace vystavit útokům CSRF (Cross-Site Request Forgery). Všechny zachované stavy relace musí chránit před útoky CSRF. Další informace najdete v tématu Prevence útoků založených na padělání žádosti posílané mezi weby (XSRF/CSRF) v ASP.NET Core.
Skrytá pole
Data lze uložit do skrytých polí formuláře a publikovat zpět na další požadavek. To je běžné ve vícestrákových formulářích. Vzhledem k tomu, že klient může potenciálně manipulovat s daty, musí aplikace vždy znovu obnovit data uložená ve skrytých polích.
HttpContext.Items
Kolekce HttpContext.Items se používá k ukládání dat při zpracování jednoho požadavku. Obsah kolekce se po zpracování požadavku zahodí. Kolekce Items
se často používá k tomu, aby komponenty nebo middleware komunikovaly, když během požadavku pracují v různých bodech v čase a nemají přímý způsob předávání parametrů.
V následujícím příkladu middleware přidá isVerified
do Items
kolekce:
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"]}");
});
});
}
U middlewaru, který se používá jenom v jedné aplikaci, jsou pevné string
klíče přijatelné. Middleware sdílený mezi aplikacemi by měl používat jedinečné klíče objektů, aby nedocházelo ke kolizím klíčů. Následující příklad ukazuje, jak použít jedinečný klíč objektu definovaný v middlewarové třídě:
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>();
}
}
Jiný kód má přístup k hodnotě uložené v HttpContext.Items
klíči vystavené middlewarovou třídou:
HttpContext.Items
.TryGetValue(HttpContextItemsMiddleware.HttpContextItemsMiddlewareKey,
out var middlewareSetValue);
SessionInfo_MiddlewareValue =
middlewareSetValue?.ToString() ?? "Middleware value not set!";
Tento přístup má také výhodu odstranění použití klíčových řetězců v kódu.
Mezipaměť
Ukládání do mezipaměti je efektivní způsob, jak ukládat a načítat data. Aplikace může řídit životnost položek uložených v mezipaměti. Další informace najdete v tématu Ukládání odpovědí do mezipaměti v ASP.NET Core.
Data uložená v mezipaměti nejsou přidružená ke konkrétnímu požadavku, uživateli nebo relaci. Neukádejte data specifická pro uživatele, která mohou být načtena jinými požadavky uživatelů.
Pokud chcete ukládat data do mezipaměti pro celou aplikaci, přečtěte si téma Mezipaměť v paměti v ASP.NET Core.
Běžné chyby
"Nelze přeložit službu pro typ Microsoft.Extensions.Caching.Distributed.IDistributedCache při pokusu o aktivaci Microsoft.AspNetCore.Session.DistributedSessionStore."
Příčinou je obvykle selhání konfigurace aspoň jedné
IDistributedCache
implementace. Další informace najdete v tématu Distribuované ukládání do mezipaměti v ASP.NET Core a mezipaměti v paměti v ASP.NET Core.
Pokud se middleware relace nepodaří zachovat relaci:
- Middleware zaznamená výjimku a požadavek pokračuje normálně.
- To vede k nepředvídatelným chováním.
Middleware relace nemůže zachovat relaci, pokud záložní úložiště není k dispozici. Uživatel například ukládá nákupní košík v relaci. Uživatel přidá položku do košíku, ale potvrzení se nezdaří. Aplikace o chybě neví, takže hlásí uživateli, že byla položka přidána do košíku, což není pravda.
Doporučeným přístupem ke kontrole chyb je volání await feature.Session.CommitAsync
při zápisu aplikace do relace. CommitAsync vyvolá výjimku, pokud záložní úložiště není k dispozici. Pokud CommitAsync
selže, aplikace může výjimku zpracovat. LoadAsync vyvolá za stejných podmínek, pokud úložiště dat není k dispozici.