Partilhar via


Implementar um Provedor de Armazenamento de Estado da Sessão

Descreve uma implementação personalizada do provedor de armazenamento de estado da sessão e demonstra implementar um provedor de exemplo.

O estado de sessão do ASP.NET foi projetado para permitir que se armazene dados da sessão de usuário em diferentes lugares.Por padrão, informações e valores do estado de sessão são armazenados na memória dentro do processo do ASP.NET.Uma alternativa é armazenar os dados da sessão em um servidor de estado, que mantém os dados da sessão num processo separado e os mantém, se o aplicativo ASP.NET for desativado e reiniciado.Outra alternativa é armazenar os dados da sessão num banco de dados SQL Server, onde ele pode ser compartilhado por vários servidores na Web.

Você pode usar os armazenamentos de estado da sessão que estão incluídos com o ASP.NET, ou você pode implementar seu próprio provedor de armazenamento de estado da sessão.Você pode criar um provedor de armazenamento de estado da sessão customizado pelas seguintes razões:

  • Você precisa armazenar informações de estado de sessão em uma fonte de dados diferente do servidor SQL, como um banco de dados FoxPro ou um banco de dados Oracle.

  • Você precisa gerenciar informações do estado de sessão usando um esquema de banco de dados que seja diferente do esquema do banco de dados usado pelos provedores fornecidos com o .NET Framework.Um exemplo disso poderia ser os dados de um carrinho de compras que são armazenados num esquema predefinido no seu banco de dados SQL Server existente.

Você pode implementar um provedor de armazenamento de estado da sessão customizado, criando uma classe que herda da classe SessionStateStoreProviderBase.Para mais informações, consulte a seção "Classes necessárias" adiante neste tópico.

O Módulo do Estado de Sessão

O estado da sessão é gerenciado pela classe SessionStateModule, que chama o provedor de armazenamento de estado da sessão para ler e gravar dados da sessão no armazenamento de dados em momentos diferentes durante uma solicitação.No início de uma solicitação, a instância SessionStateModule recupera dados pela fonte chamando o método GetItemExclusive, ou se o atributo de página EnableSessionState foi definido como ReadOnly, chamando o método GetItem.No participante de uma solicitação, se o valor do estado da sessão tiver sido modificado, a SessionStateModule chamadas da instância do SessionStateStoreProviderBase.SetAndReleaseItemExclusive método para gravar os valores atualizados para o armazenamento de estado de sessão. SessionStateModule chama membros adicionais das SessionStateStoreProviderBase implementação para iniciar uma nova sessão bem sistema autônomo para excluir dados de sessão nos dados de armazenamento quando o HttpSessionState.Abandon método é chamado. Cada membro da classe SessionStateStoreProviderBase será abordado com mais detalhes na seção "Classes necessárias" posteriormente neste tópico.

A classe SessionStateModule determina o valor SessionID por ela própria, em vez de depender do provedor de armazenamento de estado de sessão para fazer isso.Se necessário, você pode implementar um SessionIDManager customizado criando uma classe que herda a interface ISessionIDManager.Para obter mais informações, consulte a seção de comentários em ISessionIDManager.

SessionStateModule será revertido para a identidade do processo ASP.NET para acessar qualquer recurso protegido, como um servidor de banco de dados.Você pode especificar que a instância SessionStateModule represente a identidade fornecida pelo IIS definindo o atributo useHostingIdentity do elemento de configuração <sessionState> para false.Por exemplo, se você tiver configurado seu aplicativo do IIS para usar a Segurança Integrada do Windows e você desejar que o ASP.NET represente a identidade fornecida pelo IIS para o gerenciamento de sessão, especifique <identity impersonate="true" /> na seção de configuração <system.web> do arquivo web.config do aplicativo e definir o atributo useHostingIdentity do elemento de configuração <sessionState> para false.Se o atributo useHostingIdentity for true, o ASP.NET representará a identidade do processo ou as credenciais do usuário fornecidas para o elemento de configuração <identity> (se existirem), durante a conexão com a fonte de dados.Para obter mais informações sobre a identidade de processo do ASP.NET, consulte Configurando Identidade de Processo do ASP.NET e ASP.NET Impersonation.

Bloqueando Dados de Armazenamento de Sessão

Os aplicativos ASP.NET são multithread para que possam responder às várias solicitações simultâneas.Várias solicitações simultâneas podem tentar acessar as mesmas informações de sessão.Considere uma situação em vários quadros (frames) em um conjunto de quadros (frameset) referenciam a páginas Web ASP.NET no mesmo aplicativo.As solicitações separadas para cada frame no frameset podem ser executadas no servidor Web simultaneamente em threads diferentes.Se as páginas ASP.NET para cada quadro acessam variáveis de estado da sessão, você poderá ter várias threads acessando o armazenamento de sessão simultaneamente.Para evitar colisões de dados no armazenamento de sessão e um comportamento inesperado de estado de sessão, o SessionStateModule e as classes SessionStateStoreProviderBase incluem funcionalidade que bloqueia exclusivamente o item de armazenamento de sessão para uma determinada sessão durante a execução de uma página ASP.NET.Observe que nenhum bloqueio é definido em um item do armazenamento de sessão se o atributo EnableSessionState estiver marcado como ReadOnly.No entanto, outras páginas ASP.NET no mesmo aplicativo poderão gravar no armazenamento de sessão, de forma que uma solicitação somente leitura de dados da sessão ainda precise esperar por dados bloqueados serem liberados.

Um bloqueio é definido no armazenamento dados da sessão no início da solicitação na chamada para o método GetItemExclusive.Quando a solicitação for concluída, o bloqueio será liberado durante a chamada do método SetAndReleaseItemExclusive.

Se a instância SessionStateModule encontrar os dados da sessão bloqueados durante a chamada para o GetItemExclusive ou o método GetItem, ele solicitará novamente os dados da sessão em intervalos de meio segundo até que o bloqueio será liberado ou o período de tempo especificado na propriedade ExecutionTimeout tenha decorrido.Se a solicitação atinge o tempo limite, SessionStateModule chama o método ReleaseItemExclusive para liberar os dados do armazenamento da sessão e solicita os dados nesse momento.

Dados bloqueado no armazenamento da sessão podem ter sido liberados pela chamada ao método ReleaseItemExclusive num segmento separado, antes da chamada ao método SetAndReleaseItemExclusive pela resposta atual.Isso pode causar que a instância SessionStateModule defina e libere dados do armazenamento de estado da sessão que já foram liberados e modificados por outra sessão.Para evitar essa situação, o SessionStateModule inclui um identificador de bloqueio com cada solicitação para modificar os dados bloqueados do armazenamento de sessão.Dados do armazenamento de sessão são modificados somente se o identificador de bloqueio na armazenamento coincidir com o identificador de bloqueio fornecido pelo SessionStateModule.

Excluindo Dados de Armazenamento de Sessão Expirados

Quando o método Abandon é chamado para uma sessão, os dados para essa sessão são excluídos do armazenamento usando o método RemoveItem.Se não, os dados permanecem no armazenamento de dados para atender às solicitações futuras da sessão.

O mecanismo para excluir dados de sessão expirados depende dos recursos da sua fonte de dados.Se a fonte puder ser configurada para excluir dados de sessão expirados de acordo com a propriedade de sessão Timeout, pode-se usar o método SetItemExpireCallback para referenciar o representante (delegate) do evento Session_OnEnd e chamá-lo quando excluir dados expirados da sessão.

Nome do Aplicativo

Para manter o escopo da sessão, provedores de estado de sessão armazenam informações da sessão exclusivamente para cada aplicativo.Isso permite que vários aplicativos ASP.NET usem a mesma fonte de dados sem executar um conflito se forem encontrados identificadores de sessão duplicados.

Como provedores de armazenamento de estado da sessão armazenam informações da sessão exclusivamente para cada aplicativo, será necessário garantir que seu esquema de dados, consultas e atualizações incluam o nome do aplicativo.Por exemplo, o comando a seguir pode ser usado para recuperar dados da sessão de um banco de dados.

SELECT * FROM Sessions 
  WHERE SessionID = 'ABC123' AND ApplicationName = 'MyApplication'

Como alternativa, você pode armazenar uma combinação do identificador da sessão e o nome do aplicativo como o identificador exclusivo de um item do armazenamento de dados de estado de sessão.

Classes Necessárias

Para implementar um provedor de armazenamento de estado da sessão, crie uma classe que herda a classe abstrata SessionStateStoreProviderBase.A classe SessionStateStoreProviderBase herda, por sua vez, a classe abstrata ProviderBase, portanto, deve-se implementar os membros necessários da classe ProviderBase também.As tabelas a seguir listam as propriedades e métodos que devem ser implementadas das classes abstratas ProviderBase e SessionStateStoreProviderBase e fornecem uma descrição de cada.Para exibir uma implementação de cada membro, consulte Provedor de armazenamento de estado de sessão Exemplo.

Membros ProviderBase Nescessários

Membro

Descrição

Método Initialize

Leva como entrada o nome do provedor e uma instância de definições de configuração NameValueCollection.Este método é usado para definir valores de propriedades para a instância do provedor, incluindo valores específicos de implementação e opções especificadas no arquivo de configuração (Machine.config ou Web.config).

Membros SessionStateStoreProvider Necessários

Membro

Descrição

Método InitializeRequest

Aceita como entrada a instância de HttpContext para a solicitação atual e executa qualquer inicialização exigida pelo seu provedor de armazenamento de estado de sessão.

Método EndRequest

Aceita como entrada HttpContext para a atual solicitação e executa qualquer limpeza exigida pelo seu provedor de armazenamento de estado de sessão.

Método Dispose

Libera quaisquer recursos não mais em uso pelo provedor de armazenamento de estado de sessão.

Método GetItemExclusive

Aceita como entrada uma instância de HttpContext para a solicitação atual e o valor de SessionID para a solicitação atual.Recupera valores de sessão e informações do armazenamento de dados de sessão e protege os dados do item de sessão no armazenamento de dados para a duração da solicitação.O método GetItemExclusive define vários valores de parâmetros de saída que informam a chamada SessionStateModule sobre o estado do item de estado da sessão atual na armazenamento de dados.

Se nenhum item dos dados da sessão forem encontrados no armazenamento de dados, o método GetItemExclusive define o locked parâmetro de saída para false e retorna null.Isso faz com que SessionStateModule chame o método CreateNewStoreData para criar um novo objeto SessionStateStoreData para a solicitação.

Se os dados do item de sessão são encontrados no armazenamento de dados, mas os dados estão bloqueados, o método GetItemExclusive define o parâmetro de saída locked para true, define o parâmetro de saída lockAge para a data e horário atual menos a data e horário de quando o item foi bloqueado, define o parâmetro de saída lockId para o identificador de bloqueio recuperado do armazenamento de dados e retorna null.Isso faz com que SessionStateModule chame o método GetItemExclusive novamente após um intervalo de meio segundo, para tentar recuperar as informações do item de sessão e obter um bloqueio nos dados.Se o valor do parâmetro de saída lockAge for definido para exceder o valor ExecutionTimeout, SessionStateModule chama o método ReleaseItemExclusive para limpar o bloqueio nos dados do item de sessão e, em seguida, chama o método GetItemExclusive novamente.

O parâmetro actionFlags é usado em sessões cuja propriedade Cookieless é true, quando o atributo regenerateExpiredSessionId está definido como true.Um valor actionFlags definido como InitializeItem (1) indica que a entrada no armazenamento de dados da sessão é uma nova sessão que requer inicialização.Entradas não inicializadas na armazenamento de dados são criadas pela chamada ao método CreateUninitializedItem.Se o item do armazenamento de dados da sessão já estiver inicializado, o parâmetro actionFlags é definido como zero.

Se o seu provedor oferecer suporte a sessões sem-cookies, defina o parâmetro de saída actionFlags com o valor retornado de armazenamento de dados de sessão para o item atual.Se o valor do parâmetro actionFlags para o item da sessão solicitado for igual ao valor de enumeração (1) InitializeItem, o método GetItemExclusive deverá definir o valor no armazenamento de dados para zero após definir o parâmetro actionFlagsout.

Método GetItem

Esse método executa o mesmo trabalho que o método GetItemExclusive, exceto pelo fato de que ele não tenta bloquear o item de sessão no armazenamento de dados.O método GetItem é chamado quando o atributo EnableSessionState é definido como ReadOnly.

Método SetAndReleaseItemExclusive

Utiliza como entrada a instância de HttpContext da solicitação atual, o valor SessionID da solicitação atual, um objeto SessionStateStoreData que contém os valores atuais da sessão a serem armazenados, o identificador de bloqueio para a solicitação atual e um valor que indica se os dados a ser armazenados são para uma nova sessão ou uma sessão existente.

Se o parâmetro newItem for true, o método SetAndReleaseItemExclusive insere um novo item para o armazenamento de dados com os valores fornecidos.Caso contrário, o item existente no armazenamento de dados será atualizado com os valores fornecidos e qualquer bloqueio dos dados será liberado.Observe que apenas os dados de sessão para o aplicativo atual que correspondam ao valor SessionID fornecido e valores de identificador de bloqueio são atualizados.

Depois que o método SetAndReleaseItemExclusive é chamado, o método ResetItemTimeout é chamado pelo SessionStateModule para atualizar a data e hora de expiração dos dados da sessão.

Método ReleaseItemExclusive

Utiliza como entrada a instância HttpContext da solicitação atual, o valor SessionID da solicitação atual e o identificador de bloqueio da solicitação atual, e libera o bloqueio num item do armazenamento de dados de sessão.Este método é chamado quando o método GetItem ou GetItemExclusive é chamado e o armazenamento de dados especifica se o item solicitado está bloqueado, mas a duração de bloqueio excedeu o valor ExecutionTimeout.O bloqueio é desmarcado por esse método, liberando o item para uso por outras solicitações.

Método RemoveItem

Utiliza como entrada a instância HttpContext da solicitação atual, o valor SessionID da solicitação atual e o identificador de bloqueio para a solicitação atual, e exclui as informações da sessão do armazenamento de dados onde o item corresponde ao valor SessionID fornecido, ao aplicativo atual e ao identificador de bloqueio fornecidos.Este método é chamado quando o método Abandon é chamado.

Método CreateUninitializedItem

Utiliza como entrada a instância HttpContext da solicitação atual, o valor SessionID da solicitação atual e o identificador de bloqueio para a solicitação atual e adiciona um item não inicializado para o armazenamento de dados da sessão com um valor actionFlags de InitializeItem.

O método CreateUninitializedItem é usado com sessões sem-cookies quando o atributo regenerateExpiredSessionId é definido como true, o que faz com que SessionStateModule gere um novo valor SessionID quando um ID de sessão expirada for encontrado.

O processo de geração de um novo SessionID valor requer o navegador seja redirecionado para uma URL que contém a ID de sessão recém-gerado. The CreateUninitializedItem método é chamado durante uma solicitação inicial que contém uma ID de sessão expirados. Depois de SessionStateModule adquire uma nova SessionID o valor para substituir a ID de sessão expirada, ele chama o CreateUninitializedItem Para adicionar uma entrada não inicializada com os dados do estado da sessão armazenam. O navegador é, então, redirecionado para a URL que contém o valor SessionID recém-gerado.A existência de entrada não inicializada no armazenamento de dados garante que a solicitação redirecionada com o valor SessionID recém-gerado não será confundida como uma solicitação de uma sessão expirada, e, em vez disso, é tratada como uma nova sessão.

A entrada não inicializada na armazenamento de dados está associada com o valor SessionID recém-gerado e contém apenas valores padrão, incluindo uma data de expiração e um valor que corresponde ao parâmetro actionFlags dos métodos GetItem e GetItemExclusive.A entrada não inicializada no armazenamento de estado de sessão deve incluir um valor actionFlags igual ao valor da enumeração (1) InitializeItem.Esse valor é passado para SessionStateModule com o GetItem e GetItemExclusive métodos e especificar de SessionStateModule que a sessão corrente é uma nova sessão. SessionStateModule em seguida, inicializar a nova sessão e elevar o Session_OnStart evento.

Método CreateNewStoreData

Utiliza como entrada a instância HttpContext da solicitação atual e o valor Timeout da sessão atual, e retorna um objeto novo SessionStateStoreData com um objeto vazio ISessionStateItemCollection vazio, uma coleção HttpStaticObjectsCollection e o valor especificado Timeout.A instância HttpStaticObjectsCollection do aplicativo ASP.NET pode ser recuperada usando o método GetSessionStaticObjects.

Método SetItemExpireCallback

Utiliza como entrada um delegado (delegate) que referencia o evento Session_OnEnd definido no arquivo Global.asax.Se o provedor de armazenamento de estado da sessão oferecer suporte ao evento Session_OnEnd, uma referência local ao parâmetro SessionStateItemExpireCallback é definida e o método retornará true; caso contrário, o método retornará false.

Provedor de Exemplo

Para ver um exemplo de implementação de um provedor de armazenamento de estado da sessão customizado, que gerencia informações de sessão em um banco de dados do Access, consulte Provedor de armazenamento de estado de sessão Exemplo.

Consulte também

Conceitos

Provedor de armazenamento de estado de sessão Exemplo

Visão geral sobre Estado de sessão ASP.NET

Visão Geral sobre o Gerenciamento de Estado do ASP.NET