Gerenciamento de sessão e estado no ASP.NET CoreSession and state management in ASP.NET Core

Por Rick Anderson, Kirk Larkine Diana LaRoseBy Rick Anderson, Kirk Larkin, and Diana LaRose

O HTTP é um protocolo sem estado.HTTP is a stateless protocol. Por padrão, as solicitações HTTP são mensagens independentes que não retêm valores de usuário.By default, HTTP requests are independent messages that don't retain user values. Este artigo descreve várias abordagens para preservar dados de usuário entre solicitações.This article describes several approaches to preserve user data between requests.

Exibir ou baixar código de exemplo (como baixar)View or download sample code (how to download)

Gerenciamento de estadoState management

O estado pode ser armazenado usando várias abordagens.State can be stored using several approaches. Cada abordagem é descrita posteriormente neste tópico.Each approach is described later in this topic.

Abordagem de armazenamentoStorage approach Mecanismo de armazenamentoStorage mechanism
Cookie&Cookies HTTP cookie s.HTTP cookies. Pode incluir dados armazenados usando o código do aplicativo do lado do servidor.May include data stored using server-side app code.
Estado da sessãoSession state HTTP cookie s e código do aplicativo no lado do servidorHTTP cookies and server-side app code
TempDataTempData cookieEstado de sessão ou http sHTTP cookies or session state
Cadeias de consultaQuery strings Cadeias de caracteres de consulta HTTPHTTP query strings
Campos ocultosHidden fields Campos de formulário HTTPHTTP form fields
HttpContext.ItemsHttpContext.Items Código do aplicativo do lado do servidorServer-side app code
CacheCache Código do aplicativo do lado do servidorServer-side app code

CookiesCookies

Cookies armazenam dados entre solicitações.Cookies store data across requests. Como cookie os s são enviados com cada solicitação, seu tamanho deve ser mantido no mínimo.Because cookies are sent with every request, their size should be kept to a minimum. Idealmente, apenas um identificador deve ser armazenado em um cookie com os dados armazenados pelo aplicativo.Ideally, only an identifier should be stored in a cookie with the data stored by the app. A maioria dos navegadores restringe o cookie tamanho a 4096 bytes.Most browsers restrict cookie size to 4096 bytes. Apenas um número limitado de cookie s está disponível para cada domínio.Only a limited number of cookies are available for each domain.

Como cookie os s estão sujeitos à violação, eles devem ser validados pelo aplicativo.Because cookies are subject to tampering, they must be validated by the app. Cookieos s podem ser excluídos por usuários e expiram em clientes.Cookies can be deleted by users and expire on clients. No entanto, cookie s geralmente são a forma mais durável de persistência de dados no cliente.However, cookies are generally the most durable form of data persistence on the client.

Cookieos s geralmente são usados para personalização, onde o conteúdo é personalizado para um usuário conhecido.Cookies are often used for personalization, where content is customized for a known user. O usuário é apenas identificado, e não autenticado, na maioria dos casos.The user is only identified and not authenticated in most cases. O cookie pode armazenar o nome do usuário, o nome da conta ou a ID de usuário exclusiva, como um GUID.The cookie can store the user's name, account name, or unique user ID such as a GUID. O cookie pode ser usado para acessar as configurações personalizadas do usuário, como sua cor de plano de fundo de site preferencial.The cookie can be used to access the user's personalized settings, such as their preferred website background color.

Consulte as normas gerais de proteção de dados da União Europeia (GDPR) ao emitir cookie s e lidar com questões de privacidade.See the European Union General Data Protection Regulations (GDPR) when issuing cookies and dealing with privacy concerns. Para obter mais informações, veja Suporte ao RGPD (Regulamento Geral sobre a Proteção de Dados) no ASP.NET Core.For more information, see General Data Protection Regulation (GDPR) support in ASP.NET Core.

Estado de sessãoSession state

Estado de sessão é um cenário do ASP.NET Core para o armazenamento de dados de usuário enquanto o usuário procura um aplicativo Web.Session state is an ASP.NET Core scenario for storage of user data while the user browses a web app. Estado de sessão usa um armazenamento mantido pelo aplicativo para que os dados persistam entre solicitações de um cliente.Session state uses a store maintained by the app to persist data across requests from a client. Os dados da sessão são apoiados por um cache e considerados dados efêmeras.The session data is backed by a cache and considered ephemeral data. O site deve continuar a funcionar sem os dados da sessão.The site should continue to function without the session data. Os dados críticos do aplicativo devem ser armazenados no banco de dados do usuário e armazenados em cache na sessão apenas como uma otimização de desempenho.Critical application data should be stored in the user database and cached in session only as a performance optimization.

A sessão não tem suporte em SignalR aplicativos porque um SignalR Hub pode ser executado independentemente de um contexto http.Session isn't supported in SignalR apps because a SignalR Hub may execute independent of an HTTP context. Por exemplo, isso pode ocorrer quando uma solicitação de sondagem longa é mantida aberta por um hub além do tempo de vida do contexto HTTP da solicitação.For example, this can occur when a long polling request is held open by a hub beyond the lifetime of the request's HTTP context.

ASP.NET Core mantém o estado de sessão fornecendo um cookie para o cliente que contém uma ID de sessão.ASP.NET Core maintains session state by providing a cookie to the client that contains a session ID. A cookie ID da sessão:The cookie session ID:

  • É enviado para o aplicativo com cada solicitação.Is sent to the app with each request.
  • É usado pelo aplicativo para buscar os dados da sessão.Is used by the app to fetch the session data.

Estado de sessão exibe os seguintes comportamentos:Session state exhibits the following behaviors:

  • A sessão cookie é específica para o navegador.The session cookie is specific to the browser. As sessões não são compartilhadas entre navegadores.Sessions aren't shared across browsers.
  • cookieOs s de sessão são excluídos quando a sessão do navegador termina.Session cookies are deleted when the browser session ends.
  • Se um cookie for recebido para uma sessão expirada, será criada uma nova sessão que usa a mesma sessão cookie .If a cookie is received for an expired session, a new session is created that uses the same session cookie.
  • Sessões vazias não são mantidas.Empty sessions aren't retained. A sessão deve ter pelo menos um valor definido para persistir a sessão entre solicitações.The session must have at least one value set to persist the session across requests. Quando uma sessão não é mantida, uma nova ID de sessão é gerada para cada nova solicitação.When a session isn't retained, a new session ID is generated for each new request.
  • O aplicativo mantém uma sessão por um tempo limitado após a última solicitação.The app retains a session for a limited time after the last request. O aplicativo define o tempo limite da sessão ou usa o valor padrão de 20 minutos.The app either sets the session timeout or uses the default value of 20 minutes. O estado da sessão é ideal para armazenar dados do usuário:Session state is ideal for storing user data:
    • Isso é específico para uma sessão específica.That's specific to a particular session.
    • Onde os dados não exigem armazenamento permanente entre as sessões.Where the data doesn't require permanent storage across sessions.
  • Os dados da sessão são excluídos quando a ISession.Clear implementação é chamada ou quando a sessão expira.Session data is deleted either when the ISession.Clear implementation is called or when the session expires.
  • Não há um mecanismo padrão para informar ao código do aplicativo que um navegador cliente foi fechado ou quando a sessão cookie foi excluída ou expirou no cliente.There's no default mechanism to inform app code that a client browser has been closed or when the session cookie is deleted or expired on the client.
  • Os Estados cookie de sessão s não são marcados como essenciais por padrão.Session state cookies aren't marked essential by default. O estado da sessão não funciona, a menos que o rastreamento seja permitido pelo visitante do site.Session state isn't functional unless tracking is permitted by the site visitor. Para obter mais informações, consulte Suporte a Regulamento Geral sobre a Proteção de Dados (GDPR) no ASP.NET Core.For more information, see Suporte a Regulamento Geral sobre a Proteção de Dados (GDPR) no ASP.NET Core.

Aviso

Não armazene dados confidenciais no estado de sessão.Don't store sensitive data in session state. O usuário pode não fechar o navegador e limpar a sessão cookie .The user might not close the browser and clear the session cookie. Alguns navegadores mantêm sessões válidas cookie em janelas de navegador.Some browsers maintain valid session cookies across browser windows. Uma sessão pode não estar restrita a um único usuário.A session might not be restricted to a single user. O próximo usuário pode continuar a procurar o aplicativo com a mesma sessão cookie .The next user might continue to browse the app with the same session cookie.

O provedor de cache na memória armazena dados de sessão na memória do servidor em que o aplicativo reside.The in-memory cache provider stores session data in the memory of the server where the app resides. Em um cenário de farm de servidores:In a server farm scenario:

Configurar o estado de sessãoConfigure session state

O pacote Microsoft. AspNetCore. Session :The Microsoft.AspNetCore.Session package:

  • Está incluído implicitamente pela estrutura.Is included implicitly by the framework.
  • Fornece middleware para gerenciar o estado da sessão.Provides middleware for managing session state.

Para habilitar o middleware da sessão, Startup deve conter:To enable the session middleware, Startup must contain:

O código a seguir mostra como configurar o provedor de sessão na memória com uma implementação padrão na memória de IDistributedCache:The following code shows how to set up the in-memory session provider with a default in-memory implementation of 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();
        });
    }
}

O código anterior define um tempo limite curto para simplificar o teste.The preceding code sets a short timeout to simplify testing.

A ordem do middleware é importante.The order of middleware is important. Chame UseSession After UseRouting e before UseEndpoints .Call UseSession after UseRouting and before UseEndpoints. Consulte ordenação de middleware.See Middleware Ordering.

HttpContext.Session estará disponível depois que o estado de sessão for configurado.HttpContext.Session is available after session state is configured.

HttpContext.Session não pode ser acessado antes que UseSession tenha sido chamado.HttpContext.Session can't be accessed before UseSession has been called.

Uma nova sessão com uma nova sessão cookie não pode ser criada depois que o aplicativo começa a gravar no fluxo de resposta.A new session with a new session cookie can't be created after the app has begun writing to the response stream. A exceção é registrada no log do servidor Web e não é exibida no navegador.The exception is recorded in the web server log and not displayed in the browser.

Carregue o estado de sessão de maneira assíncronaLoad session state asynchronously

O provedor de sessão padrão no ASP.NET Core carrega registros de sessão do IDistributedCache armazenamento de backup subjacente de forma assíncrona somente se o ISession.LoadAsync método for explicitamente chamado antes dos TryGetValue Set métodos, ou Remove .The default session provider in ASP.NET Core loads session records from the underlying IDistributedCache backing store asynchronously only if the ISession.LoadAsync method is explicitly called before the TryGetValue, Set, or Remove methods. Se LoadAsync não for chamado primeiro, o registro de sessão subjacente será carregado de maneira síncrona, o que pode incorrer em uma penalidade de desempenho em escala.If LoadAsync isn't called first, the underlying session record is loaded synchronously, which can incur a performance penalty at scale.

Para que os aplicativos imponham esse padrão, empacote as DistributedSessionStore DistributedSession implementações e com versões que lançam uma exceção se o LoadAsync método não for chamado antes TryGetValue , Set , ou Remove .To have apps enforce this pattern, wrap the DistributedSessionStore and DistributedSession implementations with versions that throw an exception if the LoadAsync method isn't called before TryGetValue, Set, or Remove. Registre as versões encapsuladas no contêiner de serviços.Register the wrapped versions in the services container.

Opções da sessãoSession options

Para substituir os padrões de sessão, use SessionOptions .To override session defaults, use SessionOptions.

OpçãoOption DescriçãoDescription
Cookie Determina as configurações usadas para criar o cookie .Determines the settings used to create the cookie. Name o padrão é SessionDefaults.CookieName ( .AspNetCore.Session ).Name defaults to SessionDefaults.CookieName (.AspNetCore.Session). Path o padrão é SessionDefaults.CookiePath ( / ).Path defaults to SessionDefaults.CookiePath (/). SameSite o padrão é SameSiteMode.Lax ( 1 ).SameSite defaults to SameSiteMode.Lax (1). HttpOnly o padrão é true .HttpOnly defaults to true. IsEssential o padrão é false .IsEssential defaults to false.
IdleTimeout O IdleTimeout indica por quanto tempo a sessão pode ficar ociosa antes de seu conteúdo ser abandonado.The IdleTimeout indicates how long the session can be idle before its contents are abandoned. Cada acesso à sessão redefine o tempo limite.Each session access resets the timeout. Essa configuração se aplica somente ao conteúdo da sessão, não ao cookie .This setting only applies to the content of the session, not the cookie. O padrão é de 20 minutos.The default is 20 minutes.
IOTimeout O tempo máximo permitido para carregar uma sessão do repositório ou para confirmá-la de volta para o repositório.The maximum amount of time allowed to load a session from the store or to commit it back to the store. Essa configuração pode se aplicar somente a operações assíncronas.This setting may only apply to asynchronous operations. Esse tempo limite pode ser desabilitado usando InfiniteTimeSpan .This timeout can be disabled using InfiniteTimeSpan. O padrão é 1 minuto.The default is 1 minute.

A sessão usa um cookie para rastrear e identificar solicitações de um único navegador.Session uses a cookie to track and identify requests from a single browser. Por padrão, isso cookie é chamado .AspNetCore.Session e usa um caminho de / .By default, this cookie is named .AspNetCore.Session, and it uses a path of /. Como o cookie padrão não especifica um domínio, ele não é disponibilizado para o script do lado do cliente na página (porque o HttpOnly padrão é true ).Because the cookie default doesn't specify a domain, it isn't made available to the client-side script on the page (because HttpOnly defaults to true).

Para substituir cookie os padrões de sessão, use SessionOptions :To override cookie session defaults, use 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();
}

O aplicativo usa a IdleTimeout propriedade para determinar por quanto tempo uma sessão pode ficar ociosa antes que seu conteúdo no cache do servidor seja abandonado.The app uses the IdleTimeout property to determine how long a session can be idle before its contents in the server's cache are abandoned. Essa propriedade é independente da cookie expiração.This property is independent of the cookie expiration. Cada solicitação que passa pelo Middleware da Sessão redefine o tempo limite.Each request that passes through the Session Middleware resets the timeout.

Estado de sessão é sem bloqueio.Session state is non-locking. Se duas solicitações tentarem simultaneamente modificar o conteúdo de uma sessão, a última solicitação substituirá a primeira.If two requests simultaneously attempt to modify the contents of a session, the last request overrides the first. Session é implementado como uma sessão coerente, o que significa que todo o conteúdo é armazenado junto.Session is implemented as a coherent session, which means that all the contents are stored together. Quando duas solicitações buscam modificar valores de sessão diferentes, a última solicitação pode substituir as alterações de sessão feitas pelo primeira.When two requests seek to modify different session values, the last request may override session changes made by the first.

Definir e obter valores de SessionSet and get Session values

O estado da sessão é acessado de uma classe Razor pages ou de uma PageModel Controller classe MVC com HttpContext.Session .Session state is accessed from a Razor Pages PageModel class or MVC Controller class with HttpContext.Session. Essa propriedade é uma ISession implementação.This property is an ISession implementation.

A implementação de ISession fornece vários métodos de extensão para definir e recuperar valores de inteiro e cadeia de caracteres.The ISession implementation provides several extension methods to set and retrieve integer and string values. Os métodos de extensão estão no Microsoft.AspNetCore.Http namespace.The extension methods are in the Microsoft.AspNetCore.Http namespace.

Métodos de extensão ISession:ISession extension methods:

O exemplo a seguir recupera o valor da sessão para a IndexModel.SessionKeyName chave ( _Name no aplicativo de exemplo) em uma Razor página de páginas:The following example retrieves the session value for the IndexModel.SessionKeyName key (_Name in the sample app) in a Razor Pages page:

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

...

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

O exemplo a seguir mostra como definir e obter um número inteiro e uma cadeia de caracteres:The following example shows how to set and get an integer and a string:

public class IndexModel : PageModel
{
    public const string SessionKeyName = "_Name";
    public const string SessionKeyAge = "_Age";
    const string SessionKeyTime = "_Time";

    public string SessionInfo_Name { get; private set; }
    public string SessionInfo_Age { get; private set; }
    public string SessionInfo_CurrentTime { get; private set; }
    public string SessionInfo_SessionTime { get; private set; }
    public string SessionInfo_MiddlewareValue { get; private set; }

    public void OnGet()
    {
        // Requires: using Microsoft.AspNetCore.Http;
        if (string.IsNullOrEmpty(HttpContext.Session.GetString(SessionKeyName)))
        {
            HttpContext.Session.SetString(SessionKeyName, "The Doctor");
            HttpContext.Session.SetInt32(SessionKeyAge, 773);
        }

        var name = HttpContext.Session.GetString(SessionKeyName);
        var age = HttpContext.Session.GetInt32(SessionKeyAge);

Todos os dados de sessão devem ser serializados para habilitar um cenário de cache distribuído, mesmo ao usar o cache na memória.All session data must be serialized to enable a distributed cache scenario, even when using the in-memory cache. Serializadores de cadeia de caracteres e inteiros são fornecidos pelos métodos de extensão do ISession .String and integer serializers are provided by the extension methods of ISession. Tipos complexos devem ser serializados pelo usuário por meio de outro mecanismo, como JSON.Complex types must be serialized by the user using another mechanism, such as JSON.

Use o seguinte código de exemplo para serializar objetos:Use the following sample code to serialize objects:

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

O exemplo a seguir mostra como definir e obter um objeto serializável com a SessionExtensions classe:The following example shows how to set and get a serializable object with the SessionExtensions class:

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

TempDataTempData

ASP.NET Core expõe as Razor páginas TempData ou Controller TempData .ASP.NET Core exposes the Razor Pages TempData or Controller TempData. Essa propriedade armazena dados até que eles sejam lidos em outra solicitação.This property stores data until it's read in another request. Os métodos Keep (String) e Peek (String) podem ser usados para examinar os dados sem exclusão no final da solicitação.The Keep(String) and Peek(string) methods can be used to examine the data without deletion at the end of the request. Manter marca todos os itens no dicionário para retenção.Keep marks all items in the dictionary for retention. TempData é:TempData is:

  • Útil para redirecionamento quando os dados são necessários para mais de uma única solicitação.Useful for redirection when data is required for more than a single request.
  • Implementado por TempData provedores usando o cookie estado de sessão ou s.Implemented by TempData providers using either cookies or session state.

Amostras de TempDataTempData samples

Considere a seguinte página que cria um cliente:Consider the following page that creates a customer:

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 página a seguir exibe TempData["Message"] :The following page displays TempData["Message"]:

@page
@model IndexModel

<h1>Peek Contacts</h1>

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

@*Content removed for brevity.*@

Na marcação anterior, no final da solicitação, TempData["Message"] não é excluído porque Peek é usado.In the preceding markup, at the end of the request, TempData["Message"] is not deleted because Peek is used. A atualização da página exibe o conteúdo de TempData["Message"] .Refreshing the page displays the contents of TempData["Message"].

A marcação a seguir é semelhante ao código anterior, mas usa Keep para preservar os dados no final da solicitação:The following markup is similar to the preceding code, but uses Keep to preserve the data at the end of the request:

@page
@model IndexModel

<h1>Contacts Keep</h1>

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

@*Content removed for brevity.*@

A navegação entre as páginas IndexPeek e IndexKeep não será excluída TempData["Message"] .Navigating between the IndexPeek and IndexKeep pages won't delete TempData["Message"].

O código a seguir exibe TempData["Message"] , mas no final da solicitação, TempData["Message"] é excluído:The following code displays TempData["Message"], but at the end of the request, TempData["Message"] is deleted:

@page
@model IndexModel

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

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

@*Content removed for brevity.*@

Provedores de TempDataTempData providers

O cookie provedor TempData baseado em é usado por padrão para armazenar TempData em cookie s.The cookie-based TempData provider is used by default to store TempData in cookies.

Os cookie dados são criptografados usando IDataProtector , codificados com Base64UrlTextEncoder , em seguida, em bloco.The cookie data is encrypted using IDataProtector, encoded with Base64UrlTextEncoder, then chunked. O cookie tamanho máximo é menor que 4096 bytes devido à criptografia e ao agrupamento.The maximum cookie size is less than 4096 bytes due to encryption and chunking. Os cookie dados não são compactados porque a compactação de dados criptografados pode levar a problemas de segurança, como ataques de crime e violação .The cookie data isn't compressed because compressing encrypted data can lead to security problems such as the CRIME and BREACH attacks. Para obter mais informações sobre o cookie provedor TempData baseado em, consulte CookieTempDataProvider .For more information on the cookie-based TempData provider, see CookieTempDataProvider.

Escolha um provedor de TempDataChoose a TempData provider

Escolher um provedor de TempData envolve várias considerações, como:Choosing a TempData provider involves several considerations, such as:

  • O aplicativo já usa estado de sessão?Does the app already use session state? Nesse caso, usar o provedor de estado de sessão TempData não tem nenhum custo adicional para o aplicativo além do tamanho dos dados.If so, using the session state TempData provider has no additional cost to the app beyond the size of the data.
  • O aplicativo usa TempData somente com moderação para quantidades relativamente pequenas de dados, até 500 bytes?Does the app use TempData only sparingly for relatively small amounts of data, up to 500 bytes? Nesse caso, o cookie provedor TempData adiciona um pequeno custo a cada solicitação que transporta TempData.If so, the cookie TempData provider adds a small cost to each request that carries TempData. Caso contrário, o provedor de TempData do estado de sessão pode ser útil para evitar fazer viagens de ida e volta para uma grande quantidade de dados a cada solicitação até que TempData seja consumido.If not, the session state TempData provider can be beneficial to avoid round-tripping a large amount of data in each request until the TempData is consumed.
  • O aplicativo é executado em um farm de servidores em vários servidores?Does the app run in a server farm on multiple servers? Nesse caso, não há nenhuma configuração adicional necessária para usar o cookie provedor TempData fora da proteção de dados (consulte Proteção de dados do ASP.NET Core e provedores de armazenamento de chaves).If so, there's no additional configuration required to use the cookie TempData provider outside of Data Protection (see Proteção de dados do ASP.NET Core and Key storage providers).

A maioria dos clientes da Web, como navegadores da Web, impõe limites no tamanho máximo de cada um cookie e o número total de cookie s.Most web clients such as web browsers enforce limits on the maximum size of each cookie and the total number of cookies. Ao usar o cookie provedor TempData, verifique se o aplicativo não excederá esses limites.When using the cookie TempData provider, verify the app won't exceed these limits. Considere o tamanho total dos dados.Consider the total size of the data. Conta com aumentos de cookie tamanho devido à criptografia e agrupamento.Account for increases in cookie size due to encryption and chunking.

Configurar o provedor de TempDataConfigure the TempData provider

O cookie provedor TempData baseado em é habilitado por padrão.The cookie-based TempData provider is enabled by default.

Para habilitar o provedor TempData baseado em sessão, use o AddSessionStateTempDataProvider método de extensão.To enable the session-based TempData provider, use the AddSessionStateTempDataProvider extension method. Apenas uma chamada para AddSessionStateTempDataProvider é necessária:Only one call to AddSessionStateTempDataProvider is required:

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

Cadeias de consultaQuery strings

É possível passar uma quantidade limitada de dados de uma solicitação para outra adicionando-a à cadeia de caracteres de consulta da nova solicitação.A limited amount of data can be passed from one request to another by adding it to the new request's query string. Isso é útil para capturar o estado de uma maneira persistente que permita que links com estado inserido sejam compartilhados por email ou por redes sociais.This is useful for capturing state in a persistent manner that allows links with embedded state to be shared through email or social networks. Uma vez que cadeias de consulta de URL são públicas, nunca use cadeias de consulta para dados confidenciais.Because URL query strings are public, never use query strings for sensitive data.

Além do compartilhamento indesejado, a inclusão de dados em cadeias de caracteres de consulta pode expor o aplicativo a ataques CSRF (solicitação intersite forjada) .In addition to unintended sharing, including data in query strings can expose the app to Cross-Site Request Forgery (CSRF) attacks. Qualquer estado de sessão preservado deve proteger contra ataques CSRF.Any preserved session state must protect against CSRF attacks. Para obter mais informações, consulte Impedir ataques de solicitação intersite forjada (XSRF/CSRF) no ASP.NET Core.For more information, see Impedir ataques de solicitação intersite forjada (XSRF/CSRF) no ASP.NET Core.

Campos ocultosHidden fields

Dados podem ser salvos em campos de formulário ocultos e postados novamente na solicitação seguinte.Data can be saved in hidden form fields and posted back on the next request. Isso é comum em formulários com várias páginas.This is common in multi-page forms. Uma vez que o cliente potencialmente pode adulterar os dados, o aplicativo deve sempre revalidar os dados armazenados nos campos ocultos.Because the client can potentially tamper with the data, the app must always revalidate the data stored in hidden fields.

HttpContext.ItemsHttpContext.Items

A HttpContext.Items coleção é usada para armazenar dados durante o processamento de uma única solicitação.The HttpContext.Items collection is used to store data while processing a single request. O conteúdo da coleção é descartado após uma solicitação ser processada.The collection's contents are discarded after a request is processed. A coleção Items costuma ser usada para permitir que componentes ou middleware se comuniquem quando operam em diferentes momentos durante uma solicitação e não têm nenhuma maneira direta de passar parâmetros.The Items collection is often used to allow components or middleware to communicate when they operate at different points in time during a request and have no direct way to pass parameters.

No exemplo a seguir, o middleware adiciona isVerified à Items coleção:In the following example, middleware adds isVerified to the Items collection:

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

Para middleware que é usado somente em um único aplicativo, chaves fixas string são aceitáveis.For middleware that's only used in a single app, fixed string keys are acceptable. O middleware compartilhado entre aplicativos deve usar chaves de objeto exclusivas para evitar colisões de chave.Middleware shared between apps should use unique object keys to avoid key collisions. O exemplo a seguir mostra como usar uma chave de objeto exclusiva definida em uma classe de middleware:The following example shows how to use a unique object key defined in a middleware class:

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

Outros códigos podem acessar o valor armazenado em HttpContext.Items usando a chave exposta pela classe do middleware:Other code can access the value stored in HttpContext.Items using the key exposed by the middleware class:

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

Essa abordagem também tem a vantagem de eliminar o uso de cadeias de caracteres de chave no código.This approach also has the advantage of eliminating the use of key strings in the code.

CacheCache

O cache é uma maneira eficiente de armazenar e recuperar dados.Caching is an efficient way to store and retrieve data. O aplicativo pode controlar o tempo de vida de itens em cache.The app can control the lifetime of cached items. Para obter mais informações, consulte Cache de resposta no ASP.NET Core.For more information, see Cache de resposta no ASP.NET Core.

Dados armazenados em cache não são associados uma solicitação, usuário ou sessão específico.Cached data isn't associated with a specific request, user, or session. Não armazene em cache dados específicos do usuário que possam ser recuperados por outras solicitações do usuário.Do not cache user-specific data that may be retrieved by other user requests.

Para armazenar em cache os dados de todo o aplicativo, consulte Cache na memória no ASP.NET Core .To cache application wide data, see Cache na memória no ASP.NET Core.

Erros comunsCommon errors

  • "Não é possível resolver o serviço para o tipo 'Microsoft.Extensions.Caching.Distributed.IDistributedCache' ao tentar ativar 'Microsoft.AspNetCore.Session.DistributedSessionStore'.""Unable to resolve service for type 'Microsoft.Extensions.Caching.Distributed.IDistributedCache' while attempting to activate 'Microsoft.AspNetCore.Session.DistributedSessionStore'."

    Isso geralmente é causado pela falha ao configurar pelo menos uma IDistributedCache implementação.This is typically caused by failing to configure at least one IDistributedCache implementation. Para obter mais informações, consulte Caching distribuído no ASP.NET Core e Cache na memória no ASP.NET Core.For more information, see Caching distribuído no ASP.NET Core and Cache na memória no ASP.NET Core.

Se o middleware de sessão não persistir em uma sessão:If the session middleware fails to persist a session:

  • O middleware registra a exceção e a solicitação continua normalmente.The middleware logs the exception and the request continues normally.
  • Isso leva a um comportamento imprevisível.This leads to unpredictable behavior.

O middleware de sessão pode falhar ao persistir uma sessão se o armazenamento de backup não estiver disponível.The session middleware can fail to persist a session if the backing store isn't available. Por exemplo, um usuário armazena um carrinho de compras na sessão.For example, a user stores a shopping cart in session. O usuário adiciona um item ao carrinho, mas a confirmação falha.The user adds an item to the cart but the commit fails. O aplicativo não sabe sobre a falha, assim, relata ao usuário que o item foi adicionado ao seu carrinho, o que não é verdade.The app doesn't know about the failure so it reports to the user that the item was added to their cart, which isn't true.

A abordagem recomendada para verificar se há erros é chamar await feature.Session.CommitAsync quando o aplicativo é concluído gravando na sessão.The recommended approach to check for errors is to call await feature.Session.CommitAsync when the app is done writing to the session. CommitAsync gerará uma exceção se o repositório de backup não estiver disponível.CommitAsync throws an exception if the backing store is unavailable. Se CommitAsync falhar, o aplicativo poderá processar a exceção.If CommitAsync fails, the app can process the exception. LoadAsync gera sob as mesmas condições quando o armazenamento de dados está indisponível.LoadAsync throws under the same conditions when the data store is unavailable.

SignalR e estado da sessãoSignalR and session state

SignalR os aplicativos não devem usar o estado de sessão para armazenar informações.SignalR apps should not use session state to store information. SignalR os aplicativos podem armazenar por estado de conexão no Context.Items no Hub.SignalR apps can store per connection state in Context.Items in the hub.

Recursos adicionaisAdditional resources

Hospedar o ASP.NET Core em um web farm

Por Rick Anderson, Steve Smith, Diana LaRose e Luke LathamBy Rick Anderson, Steve Smith, Diana LaRose, and Luke Latham

O HTTP é um protocolo sem estado.HTTP is a stateless protocol. Sem realizar etapas adicionais, as solicitações HTTP são mensagens independentes que não mantêm os valores de usuário nem o estado do aplicativo.Without taking additional steps, HTTP requests are independent messages that don't retain user values or app state. Este artigo descreve várias abordagens para preservar dados do usuário e estado de aplicativo entre solicitações.This article describes several approaches to preserve user data and app state between requests.

Exibir ou baixar código de exemplo (como baixar)View or download sample code (how to download)

Gerenciamento de estadoState management

O estado pode ser armazenado usando várias abordagens.State can be stored using several approaches. Cada abordagem é descrita posteriormente neste tópico.Each approach is described later in this topic.

Abordagem de armazenamentoStorage approach Mecanismo de armazenamentoStorage mechanism
Cookie&Cookies HTTP cookie s (pode incluir dados armazenados usando o código do aplicativo no lado do servidor)HTTP cookies (may include data stored using server-side app code)
Estado da sessãoSession state HTTP cookie s e código do aplicativo no lado do servidorHTTP cookies and server-side app code
TempDataTempData cookieEstado de sessão ou http sHTTP cookies or session state
Cadeias de consultaQuery strings Cadeias de caracteres de consulta HTTPHTTP query strings
Campos ocultosHidden fields Campos de formulário HTTPHTTP form fields
HttpContext.ItemsHttpContext.Items Código do aplicativo do lado do servidorServer-side app code
CacheCache Código do aplicativo do lado do servidorServer-side app code
Injeção de dependênciaDependency Injection Código do aplicativo do lado do servidorServer-side app code

CookiesCookies

Cookies armazenam dados entre solicitações.Cookies store data across requests. Como cookie os s são enviados com cada solicitação, seu tamanho deve ser mantido no mínimo.Because cookies are sent with every request, their size should be kept to a minimum. Idealmente, apenas um identificador deve ser armazenado em um cookie com os dados armazenados pelo aplicativo.Ideally, only an identifier should be stored in a cookie with the data stored by the app. A maioria dos navegadores restringe o cookie tamanho a 4096 bytes.Most browsers restrict cookie size to 4096 bytes. Apenas um número limitado de cookie s está disponível para cada domínio.Only a limited number of cookies are available for each domain.

Como cookie os s estão sujeitos à violação, eles devem ser validados pelo aplicativo.Because cookies are subject to tampering, they must be validated by the app. Cookieos s podem ser excluídos por usuários e expiram em clientes.Cookies can be deleted by users and expire on clients. No entanto, cookie s geralmente são a forma mais durável de persistência de dados no cliente.However, cookies are generally the most durable form of data persistence on the client.

Cookieos s geralmente são usados para personalização, onde o conteúdo é personalizado para um usuário conhecido.Cookies are often used for personalization, where content is customized for a known user. O usuário é apenas identificado, e não autenticado, na maioria dos casos.The user is only identified and not authenticated in most cases. O cookie pode armazenar o nome do usuário, o nome da conta ou a ID de usuário exclusiva (como um GUID).The cookie can store the user's name, account name, or unique user ID (such as a GUID). Você pode usar o cookie para acessar as configurações personalizadas do usuário, como sua cor de plano de fundo de site preferencial.You can then use the cookie to access the user's personalized settings, such as their preferred website background color.

Lembre-se das normas gerais de proteção de dados (GDPR) da União Europeia ao emitir cookie s e lidar com questões de privacidade.Be mindful of the European Union General Data Protection Regulations (GDPR) when issuing cookies and dealing with privacy concerns. Para obter mais informações, veja Suporte ao RGPD (Regulamento Geral sobre a Proteção de Dados) no ASP.NET Core.For more information, see General Data Protection Regulation (GDPR) support in ASP.NET Core.

Estado de sessãoSession state

Estado de sessão é um cenário do ASP.NET Core para o armazenamento de dados de usuário enquanto o usuário procura um aplicativo Web.Session state is an ASP.NET Core scenario for storage of user data while the user browses a web app. Estado de sessão usa um armazenamento mantido pelo aplicativo para que os dados persistam entre solicitações de um cliente.Session state uses a store maintained by the app to persist data across requests from a client. Os dados da sessão são apoiados por um cache e considerados dados efêmeros—o site deve continuar funcionando sem os dados da sessão.The session data is backed by a cache and considered ephemeral data—the site should continue to function without the session data. Os dados críticos do aplicativo devem ser armazenados no banco de dados do usuário e armazenados em cache na sessão apenas como uma otimização de desempenho.Critical application data should be stored in the user database and cached in session only as a performance optimization.

Observação

A sessão não tem suporte em SignalR aplicativos porque um SignalR Hub pode ser executado independentemente de um contexto http.Session isn't supported in SignalR apps because a SignalR Hub may execute independent of an HTTP context. Por exemplo, isso pode ocorrer quando uma solicitação de sondagem longa é mantida aberta por um hub além do tempo de vida do contexto HTTP da solicitação.For example, this can occur when a long polling request is held open by a hub beyond the lifetime of the request's HTTP context.

ASP.NET Core mantém o estado de sessão fornecendo um cookie para o cliente que contém uma ID de sessão, que é enviada ao aplicativo com cada solicitação.ASP.NET Core maintains session state by providing a cookie to the client that contains a session ID, which is sent to the app with each request. O aplicativo usa a ID da sessão para buscar os dados da sessão.The app uses the session ID to fetch the session data.

Estado de sessão exibe os seguintes comportamentos:Session state exhibits the following behaviors:

  • Como a sessão cookie é específica para o navegador, as sessões não são compartilhadas entre os navegadores.Because the session cookie is specific to the browser, sessions aren't shared across browsers.
  • cookieOs s de sessão são excluídos quando a sessão do navegador termina.Session cookies are deleted when the browser session ends.
  • Se um cookie for recebido para uma sessão expirada, será criada uma nova sessão que usa a mesma sessão cookie .If a cookie is received for an expired session, a new session is created that uses the same session cookie.
  • Sessões vazias não são mantidas—a sessão deve ter pelo menos um valor definido nela para que mantenha a sessão entre solicitações.Empty sessions aren't retained—the session must have at least one value set into it to persist the session across requests. Quando uma sessão não é mantida, uma nova ID de sessão é gerada para cada nova solicitação.When a session isn't retained, a new session ID is generated for each new request.
  • O aplicativo mantém uma sessão por um tempo limitado após a última solicitação.The app retains a session for a limited time after the last request. O aplicativo define o tempo limite da sessão ou usa o valor padrão de 20 minutos.The app either sets the session timeout or uses the default value of 20 minutes. Estado de sessão é ideal para armazenar dados de usuário específicos para uma sessão em particular, mas em que os dados não requerem armazenamento permanente entre sessões.Session state is ideal for storing user data that's specific to a particular session but where the data doesn't require permanent storage across sessions.
  • Os dados da sessão são excluídos quando a ISession.Clear implementação é chamada ou quando a sessão expira.Session data is deleted either when the ISession.Clear implementation is called or when the session expires.
  • Não há um mecanismo padrão para informar ao código do aplicativo que um navegador cliente foi fechado ou quando a sessão cookie foi excluída ou expirou no cliente.There's no default mechanism to inform app code that a client browser has been closed or when the session cookie is deleted or expired on the client.
  • Os modelos ASP.NET Core MVC e de Razor páginas incluem suporte para regulamento geral sobre a proteção de dados (GDPR).The ASP.NET Core MVC and Razor pages templates include support for General Data Protection Regulation (GDPR). Os Estados de sessão cookie não são marcados como essenciais por padrão, portanto, o estado da sessão não é funcional, a menos que o rastreamento seja permitido pelo visitante do site.Session state cookies aren't marked essential by default, so session state isn't functional unless tracking is permitted by the site visitor. Para obter mais informações, consulte Suporte a Regulamento Geral sobre a Proteção de Dados (GDPR) no ASP.NET Core.For more information, see Suporte a Regulamento Geral sobre a Proteção de Dados (GDPR) no ASP.NET Core.

Aviso

Não armazene dados confidenciais no estado de sessão.Don't store sensitive data in session state. O usuário pode não fechar o navegador e limpar a sessão cookie .The user might not close the browser and clear the session cookie. Alguns navegadores mantêm sessões válidas cookie em janelas de navegador.Some browsers maintain valid session cookies across browser windows. Uma sessão pode não estar restrita a um único usuário — . o próximo usuário pode continuar a procurar o aplicativo com a mesma sessão cookie .A session might not be restricted to a single user—the next user might continue to browse the app with the same session cookie.

O provedor de cache na memória armazena dados de sessão na memória do servidor em que o aplicativo reside.The in-memory cache provider stores session data in the memory of the server where the app resides. Em um cenário de farm de servidores:In a server farm scenario:

Configurar o estado de sessãoConfigure session state

O pacote Microsoft.AspNetCore.Session, incluído no metapacote Microsoft.AspNetCore.App, fornece middleware para gerenciar o estado de sessão.The Microsoft.AspNetCore.Session package, which is included in the Microsoft.AspNetCore.App metapackage, provides middleware for managing session state. Para habilitar o middleware da sessão, Startup deve conter:To enable the session middleware, Startup must contain:

O código a seguir mostra como configurar o provedor de sessão na memória com uma implementação padrão na memória de IDistributedCache:The following code shows how to set up the in-memory session provider with a default in-memory implementation of IDistributedCache:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDistributedMemoryCache();

        services.AddSession(options =>
        {
            // Set a short timeout for easy testing.
            options.IdleTimeout = TimeSpan.FromSeconds(10);
            options.Cookie.HttpOnly = true;
            // Make the session cookie essential
            options.Cookie.IsEssential = true;
        });

        services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseSession();
        app.UseHttpContextItemsMiddleware();
        app.UseMvc();
    }
}

A ordem do middleware é importante.The order of middleware is important. No exemplo anterior, uma exceção InvalidOperationException ocorre quando UseSession é invocado após UseMvc.In the preceding example, an InvalidOperationException exception occurs when UseSession is invoked after UseMvc. Para obter mais informações, veja Ordenação de Middleware.For more information, see Middleware Ordering.

HttpContext.Session está disponível após a configuração do estado de sessão.HttpContext.Session is available after session state is configured.

HttpContext.Session não pode ser acessado antes que UseSession tenha sido chamado.HttpContext.Session can't be accessed before UseSession has been called.

Uma nova sessão com uma nova sessão cookie não pode ser criada depois que o aplicativo começa a gravar no fluxo de resposta.A new session with a new session cookie can't be created after the app has begun writing to the response stream. A exceção é registrada no log do servidor Web e não é exibida no navegador.The exception is recorded in the web server log and not displayed in the browser.

Carregue o estado de sessão de maneira assíncronaLoad session state asynchronously

O provedor de sessão padrão no ASP.NET Core carrega registros de sessão do IDistributedCache armazenamento de backup subjacente de forma assíncrona somente se o ISession.LoadAsync método for explicitamente chamado antes dos TryGetValue Set métodos, ou Remove .The default session provider in ASP.NET Core loads session records from the underlying IDistributedCache backing store asynchronously only if the ISession.LoadAsync method is explicitly called before the TryGetValue, Set, or Remove methods. Se LoadAsync não for chamado primeiro, o registro de sessão subjacente será carregado de maneira síncrona, o que pode incorrer em uma penalidade de desempenho em escala.If LoadAsync isn't called first, the underlying session record is loaded synchronously, which can incur a performance penalty at scale.

Para que os aplicativos imponham esse padrão, empacote as DistributedSessionStore DistributedSession implementações e com versões que lançam uma exceção se o LoadAsync método não for chamado antes TryGetValue , Set , ou Remove .To have apps enforce this pattern, wrap the DistributedSessionStore and DistributedSession implementations with versions that throw an exception if the LoadAsync method isn't called before TryGetValue, Set, or Remove. Registre as versões encapsuladas no contêiner de serviços.Register the wrapped versions in the services container.

Opções da sessãoSession options

Para substituir os padrões de sessão, use SessionOptions .To override session defaults, use SessionOptions.

OpçãoOption DescriçãoDescription
Cookie Determina as configurações usadas para criar o cookie .Determines the settings used to create the cookie. Name o padrão é SessionDefaults.CookieName ( .AspNetCore.Session ).Name defaults to SessionDefaults.CookieName (.AspNetCore.Session). Path o padrão é SessionDefaults.CookiePath ( / ).Path defaults to SessionDefaults.CookiePath (/). SameSite o padrão é SameSiteMode.Lax ( 1 ).SameSite defaults to SameSiteMode.Lax (1). HttpOnly o padrão é true .HttpOnly defaults to true. IsEssential o padrão é false .IsEssential defaults to false.
IdleTimeout O IdleTimeout indica por quanto tempo a sessão pode ficar ociosa antes de seu conteúdo ser abandonado.The IdleTimeout indicates how long the session can be idle before its contents are abandoned. Cada acesso à sessão redefine o tempo limite.Each session access resets the timeout. Essa configuração se aplica somente ao conteúdo da sessão, não ao cookie .This setting only applies to the content of the session, not the cookie. O padrão é de 20 minutos.The default is 20 minutes.
IOTimeout O tempo máximo permitido para carregar uma sessão do repositório ou para confirmá-la de volta para o repositório.The maximum amount of time allowed to load a session from the store or to commit it back to the store. Essa configuração pode se aplicar somente a operações assíncronas.This setting may only apply to asynchronous operations. Esse tempo limite pode ser desabilitado usando InfiniteTimeSpan .This timeout can be disabled using InfiniteTimeSpan. O padrão é 1 minuto.The default is 1 minute.

A sessão usa um cookie para rastrear e identificar solicitações de um único navegador.Session uses a cookie to track and identify requests from a single browser. Por padrão, isso cookie é chamado .AspNetCore.Session e usa um caminho de / .By default, this cookie is named .AspNetCore.Session, and it uses a path of /. Como o cookie padrão não especifica um domínio, ele não é disponibilizado para o script do lado do cliente na página (porque o HttpOnly padrão é true ).Because the cookie default doesn't specify a domain, it isn't made available to the client-side script on the page (because HttpOnly defaults to true).

Para substituir cookie os padrões de sessão, use SessionOptions :To override cookie session defaults, use SessionOptions:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDistributedMemoryCache();

    services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    services.AddSession(options =>
    {
        options.Cookie.Name = ".AdventureWorks.Session";
        options.IdleTimeout = TimeSpan.FromSeconds(10);
        options.Cookie.IsEssential = true;
    });
}

O aplicativo usa a IdleTimeout propriedade para determinar por quanto tempo uma sessão pode ficar ociosa antes que seu conteúdo no cache do servidor seja abandonado.The app uses the IdleTimeout property to determine how long a session can be idle before its contents in the server's cache are abandoned. Essa propriedade é independente da cookie expiração.This property is independent of the cookie expiration. Cada solicitação que passa pelo Middleware da Sessão redefine o tempo limite.Each request that passes through the Session Middleware resets the timeout.

Estado de sessão é sem bloqueio.Session state is non-locking. Se duas solicitações tentarem simultaneamente modificar o conteúdo de uma sessão, a última solicitação substituirá a primeira.If two requests simultaneously attempt to modify the contents of a session, the last request overrides the first. Session é implementado como uma sessão coerente, o que significa que todo o conteúdo é armazenado junto.Session is implemented as a coherent session, which means that all the contents are stored together. Quando duas solicitações buscam modificar valores de sessão diferentes, a última solicitação pode substituir as alterações de sessão feitas pelo primeira.When two requests seek to modify different session values, the last request may override session changes made by the first.

Definir e obter valores de SessionSet and get Session values

O estado da sessão é acessado de uma classe Razor pages ou de uma PageModel Controller classe MVC com HttpContext.Session .Session state is accessed from a Razor Pages PageModel class or MVC Controller class with HttpContext.Session. Essa propriedade é uma ISession implementação.This property is an ISession implementation.

A implementação de ISession fornece vários métodos de extensão para definir e recuperar valores de inteiro e cadeia de caracteres.The ISession implementation provides several extension methods to set and retrieve integer and string values. Os métodos de extensão estão no Microsoft.AspNetCore.Http namespace (adicione uma using Microsoft.AspNetCore.Http; instrução para obter acesso aos métodos de extensão) quando o pacote Microsoft. AspNetCore. http. Extensions é referenciado pelo projeto.The extension methods are in the Microsoft.AspNetCore.Http namespace (add a using Microsoft.AspNetCore.Http; statement to gain access to the extension methods) when the Microsoft.AspNetCore.Http.Extensions package is referenced by the project. Ambos os pacotes são incluídos no metapacote Microsoft.AspNetCore.App.Both packages are included in the Microsoft.AspNetCore.App metapackage.

Métodos de extensão ISession:ISession extension methods:

O exemplo a seguir recupera o valor da sessão para a IndexModel.SessionKeyName chave ( _Name no aplicativo de exemplo) em uma Razor página de páginas:The following example retrieves the session value for the IndexModel.SessionKeyName key (_Name in the sample app) in a Razor Pages page:

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

...

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

O exemplo a seguir mostra como definir e obter um número inteiro e uma cadeia de caracteres:The following example shows how to set and get an integer and a string:

public class IndexModel : PageModel
{
    public const string SessionKeyName = "_Name";
    public const string SessionKeyAge = "_Age";
    const string SessionKeyTime = "_Time";

    public string SessionInfo_Name { get; private set; }
    public string SessionInfo_Age { get; private set; }
    public string SessionInfo_CurrentTime { get; private set; }
    public string SessionInfo_SessionTime { get; private set; }
    public string SessionInfo_MiddlewareValue { get; private set; }

    public void OnGet()
    {
        // Requires: using Microsoft.AspNetCore.Http;
        if (string.IsNullOrEmpty(HttpContext.Session.GetString(SessionKeyName)))
        {
            HttpContext.Session.SetString(SessionKeyName, "The Doctor");
            HttpContext.Session.SetInt32(SessionKeyAge, 773);
        }

        var name = HttpContext.Session.GetString(SessionKeyName);
        var age = HttpContext.Session.GetInt32(SessionKeyAge);

Todos os dados de sessão devem ser serializados para habilitar um cenário de cache distribuído, mesmo ao usar o cache na memória.All session data must be serialized to enable a distributed cache scenario, even when using the in-memory cache. Serializadores de cadeia de caracteres e inteiros são fornecidos pelos métodos de extensão do ISession ).String and integer serializers are provided by the extension methods of ISession). Tipos complexos devem ser serializados pelo usuário por meio de outro mecanismo, como JSON.Complex types must be serialized by the user using another mechanism, such as JSON.

Adicione os seguintes métodos de extensão para definir e obter objetos serializáveis:Add the following extension methods to set and get serializable objects:

public static class SessionExtensions
{
    public static void Set<T>(this ISession session, string key, T value)
    {
        session.SetString(key, JsonConvert.SerializeObject(value));
    }

    public static T Get<T>(this ISession session, string key)
    {
        var value = session.GetString(key);

        return value == null ? default(T) : 
            JsonConvert.DeserializeObject<T>(value);
    }
}

O exemplo a seguir mostra como definir e obter um objeto serializável com os métodos de extensão:The following example shows how to set and get a serializable object with the extension methods:

// Requires you add the Set and Get extension method mentioned in the topic.
if (HttpContext.Session.Get<DateTime>(SessionKeyTime) == default(DateTime))
{
    HttpContext.Session.Set<DateTime>(SessionKeyTime, currentTime);
}

TempDataTempData

ASP.NET Core expõe as Razor páginas TempData ou Controller TempData .ASP.NET Core exposes the Razor Pages TempData or Controller TempData. Essa propriedade armazena dados até que eles sejam lidos em outra solicitação.This property stores data until it's read in another request. Os métodos Keep (String) e Peek (String) podem ser usados para examinar os dados sem exclusão no final da solicitação.Keep(String) and Peek(string) methods can be used to examine the data without deletion at the end of the request. Keep () marca todos os itens no dicionário para retenção.Keep() marks all items in the dictionary for retention. TempData é particularmente útil para o redirecionamento quando os dados são necessários para mais do que uma única solicitação.TempData is particularly useful for redirection when data is required for more than a single request. TempData é implementado por TempData provedores usando o cookie estado de sessão ou s.TempData is implemented by TempData providers using either cookies or session state.

Amostras de TempDataTempData samples

Considere a seguinte página que cria um cliente:Consider the following page that creates a customer:

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 página a seguir exibe TempData["Message"] :The following page displays TempData["Message"]:

@page
@model IndexModel

<h1>Peek Contacts</h1>

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

@*Content removed for brevity.*@

Na marcação anterior, no final da solicitação, TempData["Message"] não é excluído porque Peek é usado.In the preceding markup, at the end of the request, TempData["Message"] is not deleted because Peek is used. A atualização da página é exibida TempData["Message"] .Refreshing the page displays TempData["Message"].

A marcação a seguir é semelhante ao código anterior, mas usa Keep para preservar os dados no final da solicitação:The following markup is similar to the preceding code, but uses Keep to preserve the data at the end of the request:

@page
@model IndexModel

<h1>Contacts Keep</h1>

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

@*Content removed for brevity.*@

A navegação entre as páginas IndexPeek e IndexKeep não será excluída TempData["Message"] .Navigating between the IndexPeek and IndexKeep pages won't delete TempData["Message"].

O código a seguir exibe TempData["Message"] , mas no final da solicitação, TempData["Message"] é excluído:The following code displays TempData["Message"], but at the end of the request, TempData["Message"] is deleted:

@page
@model IndexModel

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

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

@*Content removed for brevity.*@

Provedores de TempDataTempData providers

O cookie provedor TempData baseado em é usado por padrão para armazenar TempData em cookie s.The cookie-based TempData provider is used by default to store TempData in cookies.

Os cookie dados são criptografados usando IDataProtector , codificados com Base64UrlTextEncoder , em seguida, em bloco.The cookie data is encrypted using IDataProtector, encoded with Base64UrlTextEncoder, then chunked. Como o cookie é fragmentado, o cookie limite de tamanho único encontrado em ASP.NET Core 1. x não se aplica.Because the cookie is chunked, the single cookie size limit found in ASP.NET Core 1.x doesn't apply. Os cookie dados não são compactados porque a compactação de dados criptografados pode levar a problemas de segurança, como ataques de crime e violação .The cookie data isn't compressed because compressing encrypted data can lead to security problems such as the CRIME and BREACH attacks. Para obter mais informações sobre o cookie provedor TempData baseado em, consulte CookieTempDataProvider .For more information on the cookie-based TempData provider, see CookieTempDataProvider.

Escolha um provedor de TempDataChoose a TempData provider

Escolher um provedor de TempData envolve várias considerações, como:Choosing a TempData provider involves several considerations, such as:

  1. O aplicativo já usa estado de sessão?Does the app already use session state? Se for o caso, usar o provedor de TempData do estado de sessão não terá custos adicionais para o aplicativo (além do tamanho dos dados).If so, using the session state TempData provider has no additional cost to the app (aside from the size of the data).
  2. O aplicativo usa TempData apenas raramente para quantidades relativamente pequenas de dados (até 500 bytes)?Does the app use TempData only sparingly for relatively small amounts of data (up to 500 bytes)? Nesse caso, o cookie provedor TempData adiciona um pequeno custo a cada solicitação que transporta TempData.If so, the cookie TempData provider adds a small cost to each request that carries TempData. Caso contrário, o provedor de TempData do estado de sessão pode ser útil para evitar fazer viagens de ida e volta para uma grande quantidade de dados a cada solicitação até que TempData seja consumido.If not, the session state TempData provider can be beneficial to avoid round-tripping a large amount of data in each request until the TempData is consumed.
  3. O aplicativo é executado em um farm de servidores em vários servidores?Does the app run in a server farm on multiple servers? Nesse caso, não há nenhuma configuração adicional necessária para usar o cookie provedor TempData fora da proteção de dados (consulte Proteção de dados do ASP.NET Core e provedores de armazenamento de chaves).If so, there's no additional configuration required to use the cookie TempData provider outside of Data Protection (see Proteção de dados do ASP.NET Core and Key storage providers).

Observação

A maioria dos clientes da Web (como navegadores da Web) impõe limites no tamanho máximo de cada um cookie , o número total de cookie s ou ambos.Most web clients (such as web browsers) enforce limits on the maximum size of each cookie, the total number of cookies, or both. Ao usar o cookie provedor TempData, verifique se o aplicativo não excederá esses limites.When using the cookie TempData provider, verify the app won't exceed these limits. Considere o tamanho total dos dados.Consider the total size of the data. Conta com aumentos de cookie tamanho devido à criptografia e agrupamento.Account for increases in cookie size due to encryption and chunking.

Configurar o provedor de TempDataConfigure the TempData provider

O cookie provedor TempData baseado em é habilitado por padrão.The cookie-based TempData provider is enabled by default.

Para habilitar o provedor TempData baseado em sessão, use o AddSessionStateTempDataProvider método de extensão:To enable the session-based TempData provider, use the AddSessionStateTempDataProvider extension method:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
        .AddSessionStateTempDataProvider();

    services.AddSession();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseSession();
    app.UseMvc();
}

A ordem do middleware é importante.The order of middleware is important. No exemplo anterior, uma exceção InvalidOperationException ocorre quando UseSession é invocado após UseMvc.In the preceding example, an InvalidOperationException exception occurs when UseSession is invoked after UseMvc. Para obter mais informações, veja Ordenação de Middleware.For more information, see Middleware Ordering.

Importante

Se o alvo for o .NET Framework e o provedor TempData baseado em sessão for usado, adicione o pacote Microsoft.AspNetCore.Session ao projeto.If targeting .NET Framework and using the session-based TempData provider, add the Microsoft.AspNetCore.Session package to the project.

Cadeias de consultaQuery strings

É possível passar uma quantidade limitada de dados de uma solicitação para outra adicionando-a à cadeia de caracteres de consulta da nova solicitação.A limited amount of data can be passed from one request to another by adding it to the new request's query string. Isso é útil para capturar o estado de uma maneira persistente que permita que links com estado inserido sejam compartilhados por email ou por redes sociais.This is useful for capturing state in a persistent manner that allows links with embedded state to be shared through email or social networks. Uma vez que cadeias de consulta de URL são públicas, nunca use cadeias de consulta para dados confidenciais.Because URL query strings are public, never use query strings for sensitive data.

Além da possibilidade de ocorrência de compartilhamento não intencional, incluir dados em cadeias de consulta pode criar oportunidades para ataques de CSRF (solicitação intersite forjada), que podem enganar os usuários para que eles visitem sites mal-intencionados enquanto estão autenticados.In addition to unintended sharing, including data in query strings can create opportunities for Cross-Site Request Forgery (CSRF) attacks, which can trick users into visiting malicious sites while authenticated. Invasores então podem roubar dados do usuário do aplicativo ou executar ações mal-intencionadas em nome do usuário.Attackers can then steal user data from the app or take malicious actions on behalf of the user. Qualquer estado de sessão ou aplicativo preservado deve se proteger contra ataques CSRF.Any preserved app or session state must protect against CSRF attacks. Para obter mais informações, consulte Impedir ataques de solicitação intersite forjada (XSRF/CSRF) no ASP.NET Core.For more information, see Impedir ataques de solicitação intersite forjada (XSRF/CSRF) no ASP.NET Core.

Campos ocultosHidden fields

Dados podem ser salvos em campos de formulário ocultos e postados novamente na solicitação seguinte.Data can be saved in hidden form fields and posted back on the next request. Isso é comum em formulários com várias páginas.This is common in multi-page forms. Uma vez que o cliente potencialmente pode adulterar os dados, o aplicativo deve sempre revalidar os dados armazenados nos campos ocultos.Because the client can potentially tamper with the data, the app must always revalidate the data stored in hidden fields.

HttpContext.ItemsHttpContext.Items

A HttpContext.Items coleção é usada para armazenar dados durante o processamento de uma única solicitação.The HttpContext.Items collection is used to store data while processing a single request. O conteúdo da coleção é descartado após uma solicitação ser processada.The collection's contents are discarded after a request is processed. A coleção Items costuma ser usada para permitir que componentes ou middleware se comuniquem quando operam em diferentes momentos durante uma solicitação e não têm nenhuma maneira direta de passar parâmetros.The Items collection is often used to allow components or middleware to communicate when they operate at different points in time during a request and have no direct way to pass parameters.

No exemplo a seguir, middleware adiciona isVerified à coleção Items.In the following example, middleware adds isVerified to the Items collection.

app.Use(async (context, next) =>
{
    // perform some verification
    context.Items["isVerified"] = true;
    await next.Invoke();
});

Mais tarde no pipeline, outro middleware poderá acessar o valor de isVerified:Later in the pipeline, another middleware can access the value of isVerified:

app.Run(async (context) =>
{
    await context.Response.WriteAsync($"Verified: {context.Items["isVerified"]}");
});

Para middleware usado apenas por um único aplicativo, chaves string são aceitáveis.For middleware that's only used by a single app, string keys are acceptable. Middleware compartilhado entre instâncias do aplicativo deve usar chaves de objeto únicas para evitar colisões de chaves.Middleware shared between app instances should use unique object keys to avoid key collisions. O exemplo a seguir mostra como usar uma chave de objeto exclusiva definida em uma classe de middleware:The following example shows how to use a unique object key defined in a middleware class:

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 builder)
    {
        return builder.UseMiddleware<HttpContextItemsMiddleware>();
    }
}

Outros códigos podem acessar o valor armazenado em HttpContext.Items usando a chave exposta pela classe do middleware:Other code can access the value stored in HttpContext.Items using the key exposed by the middleware class:

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

Essa abordagem também tem a vantagem de eliminar o uso de cadeias de caracteres de chave no código.This approach also has the advantage of eliminating the use of key strings in the code.

CacheCache

O cache é uma maneira eficiente de armazenar e recuperar dados.Caching is an efficient way to store and retrieve data. O aplicativo pode controlar o tempo de vida de itens em cache.The app can control the lifetime of cached items.

Dados armazenados em cache não são associados uma solicitação, usuário ou sessão específico.Cached data isn't associated with a specific request, user, or session. Tenha cuidado para não armazenar em cache dados específicos do usuário que podem ser recuperados pelas solicitações de outros usuários.Be careful not to cache user-specific data that may be retrieved by other users' requests.

Para obter mais informações, consulte Cache de resposta no ASP.NET Core.For more information, see Cache de resposta no ASP.NET Core.

Injeção de dependênciaDependency Injection

Use a Injeção de dependência para disponibilizar dados para todos os usuários:Use Dependency Injection to make data available to all users:

  1. Defina um serviço que contenha os dados.Define a service containing the data. Por exemplo, uma classe denominada MyAppData está definida:For example, a class named MyAppData is defined:

    public class MyAppData
    {
        // Declare properties and methods
    }
    
  2. Adicione a classe de serviço a Startup.ConfigureServices:Add the service class to Startup.ConfigureServices:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<MyAppData>();
    }
    
  3. Consuma a classe de serviço de dados:Consume the data service class:

    public class IndexModel : PageModel
    {
        public IndexModel(MyAppData myService)
        {
            // Do something with the service
            //    Examples: Read data, store in a field or property
        }
    }
    

Erros comunsCommon errors

  • "Não é possível resolver o serviço para o tipo 'Microsoft.Extensions.Caching.Distributed.IDistributedCache' ao tentar ativar 'Microsoft.AspNetCore.Session.DistributedSessionStore'.""Unable to resolve service for type 'Microsoft.Extensions.Caching.Distributed.IDistributedCache' while attempting to activate 'Microsoft.AspNetCore.Session.DistributedSessionStore'."

    Geralmente, isso é causado quando não é configurada pelo menos uma implementação de IDistributedCache.This is usually caused by failing to configure at least one IDistributedCache implementation. Para obter mais informações, consulte Caching distribuído no ASP.NET Core e Cache na memória no ASP.NET Core.For more information, see Caching distribuído no ASP.NET Core and Cache na memória no ASP.NET Core.

  • Caso a sessão de middleware não consiga manter uma sessão (por exemplo, se o repositório de backup não estiver disponível), o middleware registrará a exceção e a solicitação continuará normalmente.In the event that the session middleware fails to persist a session (for example, if the backing store isn't available), the middleware logs the exception and the request continues normally. Isso leva a um comportamento imprevisível.This leads to unpredictable behavior.

    Por exemplo, um usuário armazena um carrinho de compras na sessão.For example, a user stores a shopping cart in session. O usuário adiciona um item ao carrinho, mas a confirmação falha.The user adds an item to the cart but the commit fails. O aplicativo não sabe sobre a falha, assim, relata ao usuário que o item foi adicionado ao seu carrinho, o que não é verdade.The app doesn't know about the failure so it reports to the user that the item was added to their cart, which isn't true.

    A abordagem recomendada para verificar se há erros é chamar await feature.Session.CommitAsync(); do código de aplicativo quando o aplicativo tiver terminado de gravar na sessão.The recommended approach to check for errors is to call await feature.Session.CommitAsync(); from app code when the app is done writing to the session. CommitAsync gerará uma exceção se o repositório de backup não estiver disponível.CommitAsync throws an exception if the backing store is unavailable. Se CommitAsync falhar, o aplicativo poderá processar a exceção.If CommitAsync fails, the app can process the exception. LoadAsync gera sob as mesmas condições em que o armazenamento de dados não está disponível.LoadAsync throws under the same conditions where the data store is unavailable.

SignalR e estado da sessãoSignalR and session state

SignalR os aplicativos não devem usar o estado de sessão para armazenar informações.SignalR apps should not use session state to store information. SignalR os aplicativos podem armazenar por estado de conexão no Context.Items no Hub.SignalR apps can store per connection state in Context.Items in the hub.

Recursos adicionaisAdditional resources

Hospedar o ASP.NET Core em um web farm