Welcome to GASP Sign in | Join | Help

Paulo Morgado

Tudo sobre Arquitectura de Software
IIS/ASP.NET Cookieless Support Not Working As Expected

Num dos ambientes em que trabalho não podem ser utilizados cookies porque as páginas correm em controlos web browser hospedados numa aplicação cliente e os cookies acabam por ser partilhados entre todos os browsers.

Felizmente, o ASP.NET permite-nos persistir alguns cookies como parte do URL.

Para persistir o cookie do identificador do estado de sessão no URL basta adicionar a seguinte configuração:

<configuration>
  <system.web>
    <sessionState cookieless="UseUri" />
  </system.web>
</configuration>

e obtemos URLs destes:

http://localhost/Cookieless/(S(jcmwek3ja0lvdpbwoacpjirv))/default.aspx

O modo como o IIS e o ASP.NET fazem isto é através da remoção da secção entre parentesis por parte do IIS e a adição do valor removido como um header HTTP de nome AspFilterSessionId ao pedido. Em seguinda, o ASP.NET extrai o cookie desse header HTTP.

Fiz esta página simples para demonstrar o funcionamente desta funcionalidade:

<%@ Page Language="C#" AutoEventWireup="true" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <table>
            <tr>
                <td>Raw URL</td>
                <td><%= Request.RawUrl %></td>
            </tr>
            <tr>
                <td>Cookiless Cookies<br />AspFilterSessionId Request HTTP Header</td>
                <td><%= Request.Headers["AspFilterSessionId"] %></td>
            </tr>
            <tr>
                <td>Session ID</td>
                <td><%= Session.SessionID %></td>
            </tr>
        </table>
    </div>
    </form>
</body>
</html>

Para o URL acima, obtemos a seguinte página:

Raw URL /Cookieless/default.aspx
Cookiless Cookies
AspFilterSessionId Request HTTP Header
S(jcmwek3ja0lvdpbwoacpjirv)
Session ID jcmwek3ja0lvdpbwoacpjirv

O IIS também efectua esta operação para os conteúdos estáticos como folhas de estilos.

Para o testar podemos adicionar um tema. Isto pode ser conseguido adicionando uma pasta Default abaixo da pasta App_Themes e adicionando-lhe o ficheiro Styles.css:

body
{
    background-color: Yellow;
}
table, tr, td
{
    border: thin solid black;
}

e definindo o tema como tema predefinido através da eguinte configuração:

<configuration> <system.web> <sessionState cookieless="UseUri" /> <pages theme="Default"/> </system.web> </configuration>

E, de repenete, a nossa página fica mais “bonita”:

Raw URL /Cookieless/default.aspx
Cookiless Cookies
AspFilterSessionId Request HTTP Header
S(jcmwek3ja0lvdpbwoacpjirv)
Session ID jcmwek3ja0lvdpbwoacpjirv

Se, por alguma razão, necessitamos de providenciar os nossos próprios identificadores de sessão, podemos implementar o nosso próprio gestor de identificadores de sessão.

Mas, se queremos tirar partido dos cookieless cookies, só há um modo: extender a classe SessionIDManager:

public class SessionIdManager : System.Web.SessionState.SessionIDManager
{
    public override string CreateSessionID(System.Web.HttpContext context)
    {
        string id = System.Guid.NewGuid().ToString("B");

        return id;
    }

    public override bool Validate(string id)
    {
        try
        {
            new System.Guid(id);
            return true;
        }
        catch
        {
            return false;
        }
    }
}

e configura o sistema de estado e sessão para o usar:

<configuration>
  <system.web>
    <sessionState cookieless="UseUri" sessionIDManagerType="SessionIdManager" />
    <pages theme="Default"/>
  </system.web>
</configuration>

E obtemos esta simpática página:

http://localhost/Cookieless/(S(%7b0861e55a-e29b-4b6f-825b-1e1d4c57f095%7d))/default.aspx

Raw URL /Cookieless/(S({0861e55a-e29b-4b6f-825b-1e1d4c57f095}))/default.aspx
Cookiless Cookies
AspFilterSessionId Request HTTP Header
 
Session ID {0861e55a-e29b-4b6f-825b-1e1d4c57f095}

Eh lá! O que é que se passou aqui?

Parece que o IIS não conseguiu transferir os cookies para o header HTTP apropriado mas ASP.NET conseguiu encontrar o recurso pedido. Por outro lado, o IIS não conseguiu encontrar o ficheiro http://localhost/Cookieless/(S(%7b0861e55a-e29b-4b6f-825b-1e1d4c57f095%7d))App_Themes/Default/Styles.css.

Isto acontece em todos estes ambientes:

Operating System IIS ASP.NET
Windows XP Pro SP3 5.1 2.0 SP1, 3.5
Windows Server 2003 R2 6 2.0 SP1, 3.5
Windows Server 2008 7 2.0 SP1, 3.5

Felizmente, com o IIS 7 podem-se definir módulos HTTP quando em modo integrated pipeline que serão executados para todos os pedidos feitos ao IIS.

O módulo nem precisa de fazer nada. Apenas precisa de existir:

public class Module : System.Web.IHttpModule
{
    public void Dispose()
    {
    }

    public void Init(System.Web.HttpApplication context)
    {
    }
}

e ser adicionado à configuração:

<configuration>
  <system.web>
    <sessionState cookieless="UseUri" sessionIDManagerType="SessionIdManager" />
    <pages theme="Default"/>
  </system.web>
  <system.webServer>
    <modules>
      <add name="Module" preCondition="integratedMode" type="Module" />
    </modules>
  </system.webServer>
</configuration>

E a nossa “linda” página está de volta:

Raw URL /Cookieless/default.aspx
Cookiless Cookies
AspFilterSessionId Request HTTP Header
S({0861e55a-e29b-4b6f-825b-1e1d4c57f095})
Session ID {0861e55a-e29b-4b6f-825b-1e1d4c57f095}

Sou só eu a pensar isto, ou há aqui qualquer coisa errada?

Foi por isso que submeti este erro no Microsoft Connect

Posted: Friday, August 01, 2008 2:17 AM by Paulo Morgado

Comments

No Comments

Leave a Comment

(required) 

(required) 

(optional)

(required) 

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS