Gerenciamento de Sessão no ASP.NET

Ricardo Oneda
Microsoft MVP, MCAD
Outubro 2010

Tecnologias: Visual Studio 2010, .NET Framework 4, C# e ASP.NET

 

Sumário: Neste artigo, será mostrado como funciona o gerenciamento de sessão em aplicações ASP.NET, quais os modelos que temos para trabalhar com o controle de sessão e como podemos tirar proveito deles para conseguirmos a máxima escalabilidade de uma aplicação ASP.NET.

Baixe o códifo fonte

Conteúdo

arrow_down.gifIntrodução
arrow_down.gifAmbiente de Sessão
arrow_down.gifAmbiente de Sessão sem Cookies
arrow_down.gifConfigurações do Ambiente de Sessão
arrow_down.gifConclusão
arrow_down.gifReferências + Tópicos Relacionados
arrow_down.gifSobre o Autor

Introdução

O controle de sessão de uma aplicação web está diretamente ligado ao gerenciamento de estado da aplicação. De forma simplificada, podemos definir que o estado de uma página web é composto, basicamente, por todas as informações de uma página e seus controles ou campos de formulários. Aplicações web utilizam o HTTP (Hypertext Transfer Protocol), que é um protocolo de comunicação utilizado no transporte das requisições e respostas entre o browser e o servidor web. O HTTP é um protocolo stateless, ou seja, um protocolo sem estado, o que, na prática, significa que ele não mantém o estado entre as requisições e respostas. Assim, cada requisição feita por um cliente é tratada como se fosse uma nova, independente, não sendo mantida nenhuma relação de histórico das requisições feitas. Em aplicações desktop, os desenvolvedores não precisam se preocupar como o gerenciamento de estado, pois isso é feito de forma automática e transparente. Entretanto, isso não ocorre com as aplicações web devido à natureza do protocolo HTTP, que é a base desse tipo de aplicação. O ASP.NET oferece alguns mecanismos para contornar essa limitação. Um desses mecanismos é o ambiente de Sessão, que será detalhado neste artigo.

Ambiente de Sessão

O principal objetivo da Sessão do ASP.NET é identificar e diferenciar cada um dos usuários que estão acessando a aplicação ASP.NET, criando um ambiente de memória exclusivo para cada um deles no servidor onde a aplicação é executada. Uma aplicação web desenvolvida em ASP.NET cria um ambiente de sessão para um usuário no primeiro acesso de uma instância de browser que o mesmo faz à aplicação. Isso significa que, caso o usuário abra duas instâncias de browsers em um mesmo computador e acesse uma aplicação ASP.NET, serão criadas duas sessões, uma para cada instância de browser, cada uma em seu devido contexto. Cada sessão de cada usuário é identificada através de um identificador de Sessão único, chamado de SessionID, enviado ao browser através de um cookie não-persistente ou na URL, dependendo de como a aplicação estiver configurada. Assim, depois da primeira requisição, o SessionID sempre será enviado pelo browser de volta para o servidor web nas requisições seguintes, possibilitando ao servidor identificar de qual usuário partiu a requisição, dando consistência à aplicação e evitando que, por exemplo, um usuário tenha acesso a informações de outro usuário.

Além disso, o ASP.NET também permite que utilizemos o ambiente de Sessão para armazenar dados  de cada usuário que possui uma Sessão ativa na aplicação. Isso é possível através da propriedade Session, que é uma instância da classe HttpSessionState, exposta pelo objeto Page. Os dados são armazenados em variáveis de Sessão, em uma estrutura de dicionário na forma de pares chave-valor. É através da propriedade Session que temos acesso aos principais recursos do ambiente de Sessão do ASP.NET.

Vamos a um exemplo prático de como utilizar os recursos da Sessão do ASP.NET. Abra o Visual Studio 2010 e crie um novo projeto do tipo Web Application, utilizando a linguagem C#. O objetivo desse exemplo será demonstrar os conceitos básicos envolvendo o gerencimento de Sessão. Esses conceitos valem tanto para aplicações ASP.NET baseadas no modelo WebForms quanto para aplicações ASP.NET baseadas no modelo MVC. A aplicação que será desenvolvida irá armazenar informações na Sessão e recuperá-las. Além disso, a página também exibirá qual o SessionID daquela Sessão do usuário. A página deverá ficar parecida com a Figura 1. Não se preocupe com em tornar a página visualmente agradável. O objetivo aqui é mostrar os conceitos.

Figura 1 – Aplicação de exemplo de gerenciamento de Sessão no ASP.NET

No evento Load da página, que é executado quando a mesma é carregada, iremos recuperar exibir o valor da propriedade SessionID do objeto Session, conforme Listagem 1.

protected void Page_Load(object sender, EventArgs e)
{
    lblSessionID.Text = String.Format("Session ID: {0}", Session.SessionID);
}

Listagem 1 – Evento Load da página

O botão “Armazenar Sessão”, quando clicado, deverá gravar, no contexto da Sessão do usuário, o conteúdo do que foi digitado na caixa de texto. Nesse caso, é criada a variável de Sessão chamada “Conteudo”. Já o botão “Ler Sessão” será responsável por exibir na página o conteúdo que está armazenado na Sessão. Antes de exibir o conteúdo, precisamos verificar se a variável de Sessão que desejamos acessar existe, para somente depois acessarmos o seu valor. Isso é conseguido através do código mostrado na Listagem 2.

protected void btnArmazenar_Click(object sender, EventArgs e)
{
    Session["Conteudo"] = txtConteudo.Text;
    lblMensagem.Text = "Conteúdo armazenado na Sessão";
}

protected void btnLer_Click(object sender, EventArgs e)
{
    if (Session["Conteudo"] != null)
    {
      lblMensagem.Text = String.Format("Conteúdo da Sessão: {0}", Session["Conteudo"].ToString());
    }
}

Listagem 2 – Evento Click dos botões “Armazenar Sessão” e “Ler Sessão”

Ao executar a aplicação e a página ser carregada, note que a mesma já irá exibir o SessionID da Sessão que acabou de ser criada. Lembre-se que, conforme foi explicado anteriormente, o contexto de Sessão é criado no primeiro acesso a uma aplicação ASP.NET feito a partir de uma instância de browser. Abra uma nova instância de browser e acesse a mesma aplicação. Perceba que um novo SessionID é exibido, pois, como o acesso foi feito de uma outra instância de browser, uma nova Sessão foi criada. Digite algo na caixa de texto e clique no botão “Armazenar Sessão”. Nesse momento, o valor digitado foi armazenado na Sessão. Para se certificar de que isso é verdade, clique no botão “Ler Sessão” e veja que o valor armazenado é recuperado da Sessão e exibido na página.

Ambiente de Sessão sem cookies

Como explicado anteriormente, por padrão, o SessionID de cada sessão é enviado para o cliente através de um cookie não-persistente. Entretanto, devemos considerar que o usuário pode ter configurado o browser para não aceitar cookies. Para resolver este problema, o ASP.NET permite a criação da sessão sem o uso de cookie, o que é chamado de Cookieless Session. Neste caso, os dados do SessionID são adicionados à URL da página. Para utilizarmos Cookieless Session, devemos atribuir o valor UseUri ao atributo cookieless do elemento <sessionState> do arquivo de configuração web.config, como no exemplo da Listagem 3:

<sessionState cookieless="UseUri" />

Listagem 3 – Configurando Cookieless Session no web.config

Execute novamente a aplicação. Perceba que, desta vez, o SessionID gerado é exibido na URL apresentada na barra de endereços do browser. Esse é o mesmo SessionID que é exibido no evento Load da página, conforme Figura 2.


Figura 2 – Exemplo de Cookieless Session

O atributo cookieless pode possuir os seguintes valores:

Valor Descrição
UseUri O SessionID é armazenado na URL.
UseCookies O SessionID é armazenado em um cookie. Esse é o valor padrão do atributo cookieless.
AutoDetect Nesse caso, o ASP.NET tenta identificar se o browser ou dispositivo que está acessando a aplicação tem suporte a cookies. Em caso positivo, o cookie é utilizado. Caso contrário, utiliza-se o modelo cookieless. É importante notar que o ASP.NET não tem como identificar se o uso de cookies está desabilitado no browser. Assim, pode ser que o browser suporte cookies mas esteja com os mesmos desabilitados. Nesse cenário, o ASP.NET tentará utilizar cookies, já que ele determina se o suporte existe, e não se está habilitado.
UseDeviceProfile Nessa situação, o ASP.NET tenta identificar se o browser ou dispositivo que está acessando a aplicação tem suporte a cookies, baseado nas configurações da classe System.Web.HttpBrowserCapabilities. Em caso positivo, o cookie é utilizado. Caso contrário, utiliza-se o modelo cookieless.

É importante alertar que o uso de Cookieless Session, apesar de ser mais versátil, é menos seguro do que se utilizássemos cookie, já que o SessionID fica exposta na URL. Isso significa que, caso alguém consiga obter a URL com o SessionID de um usuário, bastará utilizá-la em qualquer browser para que essa pessoa se passe pelo usuário original, tendo então acesso ao ambiente de sessão dele e resultando em um roubo de identidade. Outro ponto de atenção é que, caso você utilize a biblioteca do ASP.NET AJAX em sua aplicação, o uso de Cookieless Session não é suportado, devendo-se utilizar a configuração padrão UseCookies.

Eventos de Sessão

O ASP.NET oferece dois eventos relacionados ao ambiente de Sessão. O primeiro deles é o Session_OnStart, que é disparado quando uma nova Sessão se inicia. O segundo, é o evento Session_OnEnd, que é disparado quando uma Sessão expira, quando o método Abandon da classe HttpSessionState é executado ou quando uma aplicação ASP.NET é encerrada. Em ambos os casos, podemos escrever código que será executado nesses eventos através do arquivo Global.asax, conforme exemplo da Listagem 4:

void Session_Start(object sender, EventArgs e)
{
    // Escreva aqui o código que será executado quando uma Sessão for criada

}

void Session_End(object sender, EventArgs e)
{
    // Escreva aqui o código que será executado quando uma Sessão for encerrada

}

Listagem 4 – Exemplo dos eventos de Sessão no arquivo Global.asax

Um equívoco que muitas pessoas comentem é achar que o evento Session_OnEnd é disparado automaticamente quando o usuário fecha o browser ou quando acessa outro site. Não existe relação entre esses eventos. O fechamento do browser ou a mudança de site são eventos que ocorrem no lado cliente da aplicação (computador do usuário), onde o ASP.NET não tem como atuar, enquanto que o evento Session_OnEnd é um evento que ocorre no servidor. Caso seja necessário identificar quando o usuário fecha o browser ou acessa outro site, deverá ser utilizado algum mecanismo em javascript para que o mesmo acione a aplicação ASP.NET no servidor quando um desses eventos ocorrer.

Configurações do ambiente de Sessão

O elemento <sessionState> do web.config possui uma série de atributos além daquele que permite utilizarCookieless Session. Esses atributos permitem configurar várias características do ambiente de Sessão do ASP.NET. Vamos examinar os principais atributos de configuração.

Local de armazenamento da Sessão

O atributo mode do elemento <sessionState> define em que local ficarão armazenados os dados da Sessão. Por padrão, o valor desse atributo é InProc, o que significa que os dados da Sessão ficarão armazenados em memória, no mesmo processo do ASP.NET. Assim, se o processo do ASP.NET se encerrar por qualquer motivo ou se o serviço do Internet Information Services (IIS – servidor web da Microsoft) for parado, toda a informação de Sessão que estiver armazenada na memória será perdida.

Outra desvantagem desse tipo de armazenamento ocorre quando a aplicação ASP.NET está distribuída em vários servidores web, um ambiente conhecido como Web Farm, muito utilizado para aumentar a escalabilidade da solução em sites com grande quantidade de usuários e acessos. Nesse caso, quando os usuários acessam o site, é feito o balanceamento da carga, que distribui esses usuários entre os vários servidores existentes, de forma transparente, ou seja, para o usuário final é como se houvesse um único servidor. Neste cenário, se um usuário for atendido pelo ServidorWeb1 ,e numa próxima requisição, for atendido pelo ServidorWeb2, teremos um problema, pois os dados da Sessão estão armazenados na memória do ServidorWeb1, que é inacessível para o ServidorWeb2. Para este tipo de situação, o ASP.NET nos permite configurar o uso de um servidor de estado externo aos servidores web, através de duas técnicas: ASP.NET State Service e SQL Server.

O ASP.NET State Service é um serviço do Windows que serve única e exclusivamente para gerenciar o ambiente de Sessão do ASP.NET. Esse serviço fica disponível quando o ASP.NET e o .NET Framework são instalados, conforme Figura 3. A grande vantagem dessa abordagem é que esse serviço pode ser configurado em um servidor diferente dos servidores web onde são executadas as aplicações ASP.NET. Esse servidor, chamado de servidor de estado, é compartilhado entre os vários servidores da Web Farm. Dessa maneira, não importa o servidor web para o qual a requisição do usuário foi direcionada, pois todos os servidores web terão condições de recuperar as informações da Sessão do usuário no servidor de estado. Além disso, se um dos servidores da Web Farm tiver algum problema, os dados da Sessão não serão perdidos, pois estarão armazenados na memória do servidor de estado. Uma desvantagem é que, como o servidor de estado está rodando em um outro processo em outra máquina, o acesso aos dados da Sessão é mais lento que o modelo InProc.


Figura 3 – ASP.NET State Service

Para se utilizar o ASP.NET State Service, basta configurar o atributo mode do elemento <sessionState> com o valor StateServer. Além disso, o atributo stateConnectionString também precisa ser configurado com o nome e a porta do servidor de estado, conforme exemplo da Listagem 5:

<sessionState 
        mode="StateServer"
        stateConnectionString="tcpip=nomeDoServidor:42424" />

Listagem 5 – Utilizando o ASP.NET State Service

Quando se utiliza o valor StateServer para armazenamento da Sessão em um ambiente de Web Farm, é necessário que a chave de criptografia especificada no elemento <machineKey> do arquivo de configuração seja a mesma em todos os servidores que fizerem parte da Web Farm.

Outra maneira de se ter um servidor de estado para armazenar os dados da Sessão do ASP.NET, é utilizar o banco de dados SQL Server da Microsoft. Para usar o SQL Server como servidor de estado, é preciso preparar o banco de dados através da ferramenta de linha de comando C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regsql.exe (os nomes dos diretórios podem ser diferentes dependendo da versão do .NET Framework utilizada). Este aplicativo é responsável por criar o banco de dados, as tabelas e stored procedures que o ASP.NET utilizará para armazenar os dados da Sessão. Ao executar o aplicativo, deverão ser fornecidos os seguintes parâmetros:

  • Parâmetro –S seguido do nome do servidor de banco de dados;
  • As credenciais de uma conta com permissões para criação do banco de dados. Pode-se utilizar o parâmetro –E para usar o usuário atualmente logado no sistema, ou a opção –U seguida de um nome de usuário e –P seguida da senha;
  • Parâmetro –ssaad, que é responsável por indicar a criação de um banco de dados de estado;
  • Por padrão, os dados de sessão são armazenados no banco de dados TempDB do SQL Server. Neste caso, se o servidor onde o SQL Server estiver instalado for reinicializado, as informações de Sessão serão perdidas. Se você quiser que essas informações estejam disponíveis mesmo após a reinicialização do servidor, deve-se utilizar o parâmetro -sstype p, que indica que os dados da Sessão deverão ser persistidos no banco de dados ASPState, ao invés do TempDB;

A Listagem 6 mostra um exemplo de uso do aplicativo aspnet_regsql.exe:

aspnet_regsql.exe -S nomeDoServidor -E -ssadd -sstype p

Listagem 6 – Criando o banco de dados de Sessão

Após a execução da ferramenta aspnet_regsql.exe, deve-se alterar o arquivo web.config, atribuindo o valor SqlServer ao atributo mode do elemento <sessionState> e fornecendo a string de conexão do banco de dados correta no atributo sqlConnectionString, como no exemplo da Listagem 7:

<sessionState 
        mode="SqlServer"
        sqlConnectionString="data source=nomeDoServidor;Trusted_Connection=yes" />

Listagem 7 – Utilizando o SQL Server para armazenar a Sessão

Assim como no caso do ASP.NET State Service, quando se utiliza o SQL Server como servidor de estado, não importa o servidor web para o qual a requisição do usuário for direcionada, pois todos os servidores web terão acesso aos dados da Sessão através do servidor de estado. Uma desvantagem é que, assim como o ASP.NET State Service, o SQL Server está sendo executado em um outro processo em outra máquina, fazendo com que o acesso aos dados da Sessão seja mais lento que o modelo InProc.

Tempo de duração da Sessão

O atributo timeout do elemento <sessionState> especifica a quantidade de minutos que uma sessão pode ficar inativa antes de ser encerrada pelo ASP.NET. Por padrão, esse tempo é de 20 minutos. Isso significa que cada usuário poderá ficar até 20 minutos sem nenhuma interação com aplicação, com seus dados de Sessão mantidos. Após esse tempo, o ASP.NET expirará a Sessão, o que provocará a perda dos dados armazenados nela, e uma nova requisição irá criar uma nova Sessão. A Listagem 8 mostra um exemplo de configuração de um timeout de 10 minutos.

<sessionState timeout="10" />

Listagem 8 – Definindo o timeout da Sessão

Lembre-se que o uso do ambiente de Sessão do ASP.NET consome recursos do servidor. Assim, devemos ser criteriosos ao definirmos o tempo de duração da Sessão inativa, pois quanto maior o tempo, mais irá demorar para o ASP.NET liberar os recursos utilizados.

Conclusão

Neste artigo, vimos os principais conceitos relacionados ao gerenciamento de Sessão do ASP.NET, as principais configurações do ambiente de Sessão e como tirar melhor proveito dele. Existem outras configurações que podem ser feitas, mas que não foram abordadas no artigo. O leitor poderá encontrar mais informações sobre elas na seção “Referências + Tópicos Relacionados”, abaixo. Além disso, outro ponto que não foi abordado nesse artigo é que o ambiente de Sessão do ASP.NET é extensível, ou seja, permite que qualquer desenvolvedor crie seu próprio mecanismo para armazenamento dos dados da Sessão, possibilitando outras formas de armazenamento além daquelas oferecidas nativamente pelo ASP.NET. Fica aqui uma sugestão de leitura para quem estiver interessado no assunto.

Referências + Tópicos Relacionados

ASP.NET State Management Overview

ASP.NET Session State Overview

sessionState Element (ASP.NET Settings Schema)

ASP.NET State Management Recommendations

Implementing a Session-State Store Provider

Sobre o Autor

Ricardo Oneda é formado em Processamento de Dados pela Faculdade de Tecnologia de São Paulo e pós-graduado em Administração de Empresas pela Fundação Getúlio Vargas de São Paulo. É Microsoft MVP (Most Valuable Professional) em ASP.NET desde 2005 e possui a certificação MCAD (Microsoft Certified Application Developer), com ênfase em aplicações Web com C# e Banco de Dados SQL Server. Atualmente, trabalha como Analista de Sistemas no desenvolvimento de aplicações Web. Pode ser contatado em seu blog (http://oneda.mvps.org/blog/) ou através do twitter (http://twitter.com/roneda).