Desenvolvimento - ASP. NET

Definido páginas HTTPS com rapidez e segurança

Este artigo mostra uma maneira rápida e fácil de controlar a troca entre os protocolos HTTP e HTTPS com rapidez e segurança.

por Vinicius Tutuy



Atualmente é indispensável o uso do HTTPS em páginas onde há trafego de dados confidenciais. Dependendo do tamanho do sistema, essa tarefa não é muito rápida. Vou mostrar como construir um módulo (HttpModule) para controlar a troca entre os protocolos HTTP e HTTPS com rapidez e segurança.

O módulo funciona da seguinte forma:

- Quando chega uma requisição o módulo verifica se o protocolo é HTTP ou HTTPS.

- Caso seja HTTP ele verifica se a página está configurada para responder pelo HTTPS e redireciona o usuário para a página utilizando o protocolo seguro, caso contrário continua com a requisição normalmente.

- Caso seja HTTPS ele verifica se a página está configurada para responder pelo HTTPS e continua com a requisição normalmente, caso contrário redireciona o usuário para o protocolo HTTP para evitar tráfego excessivo de dados.

Após esta breve explicação da idéia, vamos aos códigos.

Desenvolvimento do Projeto

Primeiramente crie um novo projeto do tipo Class Library.

 

Criado o projeto, vamos desenvolver as classes que serão utilizadas como elementos nas configurações do Web.Config.

Pagina.cs

public class Pagina : ConfigurationElement

{

    internal Pagina(): base()

    {}

    internal Pagina(string nome) : this()

    {

        Nome = nome;

    }

    [ConfigurationProperty("nome", IsRequired = true, Options = ConfigurationPropertyOptions.IsKey)]

    public virtual string Nome

    {

        get { return this["nome"] as string; }

        set { this["nome"] = value; }

    }

}

ColecaoPaginas.cs

public class ColecaoPaginas : ConfigurationElementCollection

{

    protected override string ElementName

    {

        get { return "paginas"; }

    }

    public Pagina this[int indice]

    {

        get { return BaseGet(indice) as Pagina; }

    }

    public new Pagina this[string nome]

    {

        get { return BaseGet(nome.ToLower()) as Pagina; }

    }

    protected override object GetElementKey(ConfigurationElement elemento)

    {

        return (elemento != null) ? (elemento as Pagina).Nome.ToLower() : null;

    }

    protected override ConfigurationElement CreateNewElement()

    {

        return new Pagina();

    }

}

Secao.cs

public class Secao : ConfigurationSection

{

    [ConfigurationProperty("paginas")]

    public ColecaoPaginas Paginas

    {

        get { return this["paginas"] as ColecaoPaginas; }

    }

}

A parte de configuração já está pronta, agora vem à parte que realmente importa.

A classe Modulo.cs é uma classe que implementa IHttpModule. Está classe será responsável por receber todas as requisições e redirecionar o usuário para o protocolo correto, quando necessário.

Modulo.cs

public class Modulo : IHttpModule

{

    private struct Prefixos

    {

        public const string Inseguro = "http://";

        public const string Seguro = "https://";

    }

    public void Dispose() {}

    public void Init(HttpApplication context)

    {

        if (context != null)

        {

            Secao secao = WebConfigurationManager.GetSection("paginasSeguras") as Secao;

            if (secao != null)

            {

                context.Application["PaginasSeguras"] = secao;

                context.AcquireRequestState += new EventHandler(Application_ProcessRequest);

            }

        }

    }

    private void Application_ProcessRequest(Object source, EventArgs e)

    {

        HttpApplication context = source as HttpApplication;

        if (context != null)

        {

            Secao secao = context.Application["PaginasSeguras"] as Secao;

            ProcessarRequest(secao, context.Context);

        }

    }

    private void ProcessarRequest(Secao secao, HttpContext context)

    {

        string novaUrl = ProcurarPagina(secao, context);

        if (!string.IsNullOrEmpty(novaUrl))

            context.Response.Redirect(novaUrl, true);

    }

    private string ProcurarPagina(Secao secao, HttpContext context)

    {

        if (secao == null)

            return "";

        string cloneUri = context.Request.Url.AbsoluteUri.Clone() as string;

        int indice = cloneUri.IndexOf("?");

        string queryString = indice == -1 ? "" : cloneUri.Substring(indice);

        if (indice != -1)

            cloneUri = cloneUri.Substring(0, indice);

        if (!cloneUri.EndsWith(".aspx"))

            return null;

        string resultado = null;

        if (cloneUri.StartsWith(Prefixos.Inseguro))

        {

            resultado = SelecionarPagina(cloneUri, queryString, secao);

        }

        else if (cloneUri.StartsWith(Prefixos.Seguro))

        {

            string pagina = SelecionarPagina(cloneUri, queryString, secao);

            if (string.IsNullOrEmpty(pagina))

                resultado = cloneUri.Replace(Prefixos.Seguro, Prefixos.Inseguro) + queryString;

        }

        return resultado;

    }

    private string SelecionarPagina(string uri, string queryString, Secao secao)

    {

        if (String.IsNullOrEmpty(uri))

            return null;

        for (int i = 0; i < secao.Paginas.Count; i++)

        {

            string urlSegura = secao.Paginas[i].Nome;

            if (String.IsNullOrEmpty(urlSegura))

                continue;

            if (urlSegura[0] == "~")

                urlSegura = VirtualPathUtility.ToAbsolute(urlSegura);

            if (uri.ToLower().EndsWith(urlSegura.ToLower()))

                return uri.Replace(Prefixos.Inseguro, Prefixos.Seguro) + queryString;

        }

        return null;

    }

}

Agora só falta configurar o Web.Config para começar a validar as requisições, e redirecionar o usuário para o protocolo correto (Obs: As tags necessárias para o funcionamento do módulo estão em negrito).

Web.config

<?xml version="1.0"?>

<configuration>

      <configSections>

            <section name="paginasSeguras" type="PaginasSeguras.Secao" />

      </configSections>

      <paginasSeguras>

            <paginas>

                  <add nome="~/DadosPessoais.aspx"></add>

                  <add nome="~/Login.aspx"></add>

            </paginas>

      </paginasSeguras>

      <system.web>

            <compilation debug="true"/>

            <authentication mode="Windows"/>

            <httpModules>

                  <add name="ModuloSeguro" type="PaginasSeguras.Modulo" />

            </httpModules>

      </system.web>

</configuration>

Obrigado e até a próxima

Vinicius Tutuy

Vinicius Tutuy

Vinicius Tutuy - Analista de sistemas, especialista em desenvolvimento de soluções web. Atualmente cursa Engenharia de Computação e possui as certificações MCP e MCAD.