Novo comportamento do EventValidation

Há algum tempo eu comentei a respeito de alguns cuidados que precisamos ter com o EventValidation. Um outro cenário em que este mesmo erro está propício a acontecer, é quando estamos dentro de uma página muito complexa ou com muitas informações e que a sua renderização demora para acontecer por inteira.

O EventValidation se baseia em um campo oculto chamado __EVENTVALIDATION para validar o controle que gerou o postback. O próprio runtime do ASP.NET embuti este controle no final da página (pouco antes da tag de fechamento do formulário (</form>)), durante o processo de renderização. O grande problema que temos aqui é que as vezes, a renderização pode ocorrer parcialmente e, caso um controle que cause postback apareça para o usuário e ele clicar, um postback será efetuado sem o envio do campo oculto __EVENTVALIDATION, pois ele ainda não foi renderizado.

O Service Pack 1 do .NET Framework 3.5 resolve isso, ou seja, agora a renderização deste campo (e de todos os outros campos ocultos “auto-gerados”), por padrão, passa a ser efetuada no ínicio do formulário, permitindo assim efetuar postbacks sem esperar a página renderizar por inteira.

E, para finalizar, é importante dizer que voce pode controlar isso através do atributo renderAllHiddenFieldsAtTopOfForm do elemento pages, no arquivo Web.config:

<pages renderAllHiddenFieldsAtTopOfForm=”true|false” />

TransferRequest

Há algum tempo atrás eu mencionei aqui um grande problema que existe quando utilizamos o método Transfer da classe HttpServerUtility, principalmente quando falamos de redirecionamento para páginas restritas. Isso ocorre porque este método não executa o processo total dentro do ASP.NET pipeline. Esse foi um dos motivos que levou o Paulo Morgado a criar os Page Modules.

Para sanar este problema, a versão 3.5 do ASP.NET incluiu um novo método na classe HttpServerUtitlity chamado TransferRequest. A sua utilização é identica ao método Transfer, só que possui um comportamento totalmente diferente, ou seja, permite que a requisição para o recurso solicitado seja executado passando por todo o pipeline do ASP.NET e, sendo assim, o processo de autorização será novamente executado. Além disso, é necessário que a aplicação corra no IIS 7.0 pois, do contrário, uma exceção será atirada.

Só que para aqueles que querem utilizar esse recurso e fazem o uso de variáveis de sessão, é importante ler a nota que o Luis Abreu diz aqui.

WCF – Partial Trust

Uma das configurações mais importantes que se deve realizar em uma aplicação é a segurança, mais precisamente, que tipo de permissão devemos conceder à mesma para que ela possa ser executada. O tipo de permissão que me refiro aqui não tem a ver com a identidade do usuário, mas sim as permissões que o código (Assembly) tem para acessar recursos da máquina onde o mesmo está sendo executado.

Esse tipo de configuração foi introduzida desde a primeira versão do .NET Framework e é chamada de Code Access Security – CAS. Baseada no conceito de permissões, onde cada uma delas mapeia para um recurso (Message Queue, File System, SQL Server, etc.) da máquina, são através destas permissões que dizemos ao Runtime Security Policy (de forma declarativa ou imperativa), quais direitos nosso código tem de executar, ou melhor, a quais recursos ele terá acesso.

Se você cria qualquer aplicação .NET e não altera nenhuma configuração de segurança, ele será executado em Full Trust, ou seja, terá acesso irrestrito a qualquer recurso da máquina onde está atualmente sendo executado. Apesar disso ser muito comum, não é ideal. Uma premissa básica na segurança é jamais conceder direitos desnecessários a um código para desempenhar suas funções. Quando você opta por mudar a segurança padrão imposta pelo .NET, quer dizer que você está executando a aplicação em Partial Trust, ou seja, em um ambiente em que você não terá acesso a todos os recursos, mas sim, o essencial para a aplicação poder trabalhar.

Na primeira versão do WCF (Windows Communication Foundation) – .NET Framework 3.0 – ele não era suportado em ambientes que estavam sob Partial Trust, o que obrigava muitos clientes a conceder mais direitos do que o necessário para poder executar/invocar um serviço escrito em WCF. Depois de muitas requisições, a Microsoft decidiu afrouxar essa segurança com o lançamento do .NET Framework 3.5, permitindo (com várias restrições) que serviços sejam invocados a partir de um ambiente parcialmente confiável. Isso obrigou a Microsoft a decorar os assemblies System.ServiceModel.dll e System.ServiceModel.Web.dll com o atributo AllowPartiallyTrustedCallers que, como o nome diz, permite que o assembly seja invocado por aplicações que estão sendo executadas em um ambiente mais restrito.

Entre as limitações que o WCF 3.5 impõe, temos: permite somente os bindings BasicHttpBinding, WsHttpBinding (sem segurança ou com segurança a nível de transporte) e WebHttpBinding serem invocados a partir de uma aplicação que está sendo executada em ambiente parcialmente confiável; além disso, serviços WCF que estão rodando em aplicações de middle tier também podem invocar requisições para outros serviços, desde que tenha a sua respectiva WebPermisson, que concede direito de acesso a esse recurso. Todos os outros bindings, não HTTP, demandarão full trust de seus chamadores, obrigando-nos a conceder ao cliente mais direitos do que ele deveria ter para poder trabalhar. Para uma lista completa de todas as restrições, você pode consultar este link.

Mas e quando necessitamos referenciar em nossa aplicação parcialmente confiável, um serviço WCF que expõe apenas um endpoint com o binding definido como NetTcpBinding? Uma alternativa interessante é criar um proxy, isolando toda a chamada para este serviço. E no que consiste um proxy? Basicamente trata-se de uma DLL que conterá uma classe que servirá como um wrapper para a interface do serviço a ser acessado. Quando referenciamos o serviço diretamente na aplicação, automaticamente a IDE do Visual Studio se encarrega de criar a classe (também denominada proxy) para que possamos invocar os respectivos métodos do serviço localmente e que, durante a execução, será delegado ao serviço.

Para o nosso cenário isso não será a melhor saída. O que devemos fazer é utilizar o utilitário svcutil.exe que, entre suas utilidades, é capaz de gerar uma classe baseado no WSDL extraído do mesmo. A linha abaixo ilustra como devemos passar os parâmetros para o svcutil.exe para que o mesmo possa gerar a classe correspondente (executando a partir do prompt do Visual Studio .NET):

C:>svcutil net.tcp://localhost:9000/Mex /out:C:Proxy.cs

Uma vez que a classe é criada, criaremos um projeto do tipo Class Library e adicionaremos a classe recém criada, Proxy.cs, dentro deste projeto. Além disso, é também necessário fazer a referência para o assembly System.ServiceModel.dll. Depois deste processo, precisamos ainda fazer algumas configurações em nível de assembly; como essa DLL deverá ser consumida por um projeto que está sendo executado em um ambiente parcialmente confiável, adicionar no arquivo AssemblyInfo.cs o atributo AllowPartiallyTrustedCallers; finalmente, será necessário definir um Strong Name para essa DLL (veremos mais tarde, ainda neste artigo o motivo disso). O trecho de código abaixo ilustra como devemos proceder para definir o atributo APTCA:

using System.Security;

[assembly: AllowPartiallyTrustedCallers]

Para finalizar, é necessário abrir o arquivo Proxy.cs e, no ínicio da classe que representa o serviço do lado do cliente (ClientBase), e especificar o atributo PermissionSetAttribute, assim como é mostrado abaixo:

using System.Security;
using System.Security.Permissions;

[PermissionSetAttribute(SecurityAction.Assert, Name = "FullTrust")]
public partial class Service1Client : System.ServiceModel.ClientBase<IService1>, IService1
{
    //Implementação
}

O atributo PermissionSetAttribute irá permitir a definição de uma determinada ação para uma permission set (conjunto de permissões) específica. No exemplo acima, estamos especificando a ação Assert (via enumerador SecurityAction) sob a permission set predefinida, que é a FullTrust. A utilização da ação/método Assert deve ser analisada com muito cuidado, pois é o mesmo que “Eu sei o que estou fazendo; confie em mim!”, e isso garantirá que a permissão seja concedida ao chamador mesmo que ele não tenha privilégio para isso.

Finalmente, a DLL está pronta para ser utilizada mas se, neste momento, a mesma for referenciada na aplicação que está sendo executada em ambiente parcialmente confiável, uma exceção será atirada, dizendo que não é possível consumir um serviço via TCP nesta aplicação. Neste caso, necessitamos adicionar essa DLL no GAC, pois os componentes que lá residem já ganham Full Trust. É importante dizer que, mesmo assim, é necessário o código acima, pois o stack walk também verificará a aplicação Web que chama o componente e essa, por sua vez, não terá a permissão necessária e, consequentemente, a exceção será atirada. Esse conceito que utilizamos aqui também é conhecido como Sandboxing.

Importante: Apesar desta técnica funcionar, ela tem um ponto negativo: suprimindo a security demand, que é o processo de avaliação dos chamadores para se certificar que todos possuem tal permissão, permitirá que qualquer cliente que execute sob ambiente parcialmente confiável chame qualquer serviço WCF. Isso permitirá a um cliente que não tenha permissão de acesso a algum recurso, como acesso TCP, aplicar um bypass nesta limitação. A solução para esse problema é criar uma classe que herde diretamente da classe base ClientBase, concedendo as permissões específicas, dependendo do tipo de binding.

Conclusão: Felizmente o WCF permite na versão 3.5 do .NET Framework o consumo de serviços em ambiente parcialmente confiáveis. Alguns bindings podem ser consumidos sem a necessidade de alguma configuração adicional, pois são acessíveis em ambientes parcialmente confiáveis; já outros bindings não podem ser acessados diretamente, e necessitam de um passo adicional, que é a criação do proxy, explicado neste artigo.

Instalação padrão do Membership, Roles e Profile

As funcionalidades Membership, Roles e Profile do ASP.NET 2.0 vem por padrão habilitadas. A questão é que essa configuração padrão demanda ter instalado na máquina onde corre a aplicação (geralmente a máquina do desenvolvedor), o SQL Server Express.

Em uma aplicação recém criada não haverá nenhuma configuração no arquivo Web.Config. Se analisarmos algumas seções que estão presentes do arquivo machine.config, temos:

<connectionStrings>
    <add name=”LocalSqlServer” connectionString=”data source=.SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true” providerName=”System.Data.SqlClient”/>
</connectionStrings>

<membership>
    <providers>
        <add name=”AspNetSqlMembershipProvider” type=”System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a” connectionStringName=”LocalSqlServer” …. />
    </providers>
</membership>

Com isso, quando iniciamos o ASP.NET Configuration, ele irá tentar acessar (ou criar) esta base de dados. Se não tiver o SQL Server Express instalado, esse processo resultará em um erro. Para resolver, voce tem duas alternativas:

  1. Instalar o SQL Server Express.
  2. Configurar para um servidor SQL Server existente. Se optar por essa alternativa, voce deve configurar o seu arquivo Web.Config da seguinte forma:

<?xml version=”1.0″?>
<configuration>
  <connectionStrings>
    <clear/>
    <add
      name=”SqlConnectionString”
      connectionString=”Data Source=local;Initial Catalog=BaseDeDados;Integrated Security=True;”/>
  </connectionStrings>
  <system.web>
    <membership defaultProvider=”SqlMembershipProvider”>
      <providers>
        <clear/>
        <add
          name=”SqlMembershipProvider”
          type=”System.Web.Security.SqlMembershipProvider”
          connectionStringName=”SqlConnectionString”
          ….. />
      </providers>
    </membership>
  </system.web>
</configuration>

É importante notar que o elemento <clear /> remove a conexão e o provider do membership que são configurados por padrão. Além dessa configuração prévia, voce precisará também criar os objetos (tabelas, stored procedures e views) necessários para que essas funcionalidades trabalhem. Para isso, voce utilizará o utilitário aspnet_regsql.exe e pode encontrar maiores informações aqui.

Por dentro da Base Class Library

A Base Classe Library (também conhecida como BCL) é um conjunto de classes que o .NET disponibiliza para todas as linguagens que rodam sob o .NET Framework. Essa base encapsula várias funcionalidades que tornam o trabalho dos desenvolvedores muito mais fácil. As classes contidas dentro da BCL é comum para qualquer tipo de aplicação, ou seja, independentemente de tecnologia (ASP.NET, Windows Forns, WPF, etc.), você poderá consumir essas classes que, representam tarefas que são comumente utilizadas. A imagem abaixo exibe onde a BCL está encaixada dentro da plataforma .NET.

Figura 1Base Class Library (BCL).

A versão 2.0 adicionou novas tipos e namespaces, enriquecendo ainda mais esta estrutura. Essas classes vão desde novas coleções (tipadas) até novos namespaces, como é o caso do System.Transactions. Apesar do .NET Framework estar em sua versão 3.5, ele utiliza o .NET 2.0 como seu núcleo. A figura abaixo ilustra perfeitamente a posição do .NET 2.0 dentro do .NET 3.X.

Figura 2 – Gráfico que exibe a posição do .NET 2.0.

A BCL é composta por vários namespaces e, através dos capítulos abaixo, veremos detalhadamente cada um dos principais deles. A idéia é abordar o conteúdo mais útil ao dia-à-dia, mostrando exemplos em Visual Basic .NET e Visual C#. Sendo assim, nem todas as classes/funcionalidades serão cobertas aqui mas, para isso, poderá recorrer ao MSDN Library.

ATENÇÃO: Os arquivos estão em formato XPS. Caso não tenha o visualizador, você poderá baixá-lo aqui.

Conteúdo

  • Capítulo 1 – Tipos de dados e Interfaces Este capítulo abordará a arquitetura de tipos fornecido pelo .NET Framework, onde na primeira parte do capítulo, será abordado os tipos padrões padrões e veremos como identificar se trata-se de um tipo valor ou referência. Além disso, analisaremos um problema grave, deixado de lado por muitos desenvolvedores, que é a questão do boxing e unboxing. Ainda nessa primeira parte, analisaremos alguns novos tipos introduzidos nesta versão do .NET Framework, em principal, os Generics. Na segunda e última parte do mesmo, vamos abordar as várias Interfaces que estão disponíveis para serem implementados em tipos customizados, fornecendo funcionalidades adicionais ao tipo criado.

  • Capítulo 2 – Trabalhando com Coleções As coleções são componentes importantes em qualquer tipo de aplicação e, para isso, esse capítulo abordará extensamente o uso das mesmas, começando pelas coleções primárias, fornecidas desde as primeiras versões do .NET Framework até as novas coleções, introduzidas na versão 2.0 do .NET Framework, quais fazem uso dos Generics. Além das coleções, analisaremos as Interfaces disponíveis para podermos estender as funcionalidades existentes e customizarmos para o nosso cenário.
  • Capítulo 3 – Utilização de Assemblies Um Assembly é a menor unidade de reutilização, segurança e controle de versão. O Assembly é algo importante que deve ser analisado cuidadosamente, pois toda aplicação .NET depois de compilada gerará um Assembly. Este capítulo abordará a sua criação desde um utilitário de linha de comando até o Visual Studio .NET. Além disso, abordaremos também outros assuntos relacionados a Assemblies, como por exemplo, strong names, GAC (Global Assembly Cache), instaladores e arquivos de configuração.
  • Capítulo 4 – Monitoramento e depuração de aplicações Toda e qualquer aplicação necessita de algum tipo de monitoramento de seu código para detectar possíveis problemas que possam acontecer e que devem ser analisados. O .NET Framework fornece várias classes que ajudam nesse monitoramento e, este capítulo, é responsável por apresentar essas classes que vão desde a manipulação do Event Log do Windows até classes que interagem com o WMI – Windows Management Instrumentation.
  • Capítulo 5 – Manipulando o sistema de arquivos Grande parte das aplicações comerciais que temos atualmente manipulam arquivos. Esses arquivos são arquivos de bancos, arquivos de parceiros e fornecedores que servem para troca de informações. Enquanto os XML Web Services ainda não são uma realidade para muitas empresas, a manipulação de arquivos e seus respectivos conteúdos é ainda muito utilizado. Tendo esse cenário, o capítulo em questão abordará as principais classes contidas dentro do namespace System.IO para exemplificar e facilitar a manipulação de arquivos do disco e streams de dados.
  • Capítulo 6 – Serialização A serialização de dados é cada dia mais utilizada em aplicações. Por mais que isso aconteça nos bastidores, esse capítulo abordará desde o seu conceito até como implementá-la; e ainda, em seus diversos formatos, utilizando as classes fornecidas pelo .NET Framework 2.0. Além disso, analisaremos classes e Interfaces que temos disponíveis, que proporcionaram o processo de serialização e deserialização mais flexível, onde podemos customizar e interceptar cada um desses processos de acordo com a nossa necessidade.
  • Capítulo 7 – Globalização de Aplicações Cada vez mais se desenvolve softwares que podem ser acessados por várias pessoas de diferentes idiomas e de diferentes locais do mundo. Tendo esse cenário, é importante que a aplicação que estamos desenvolvendo seja possível ao usuário poder customizar o idioma que deseja visualizar os dados e ainda, poder criar a aplicação independente de qualquer cultura. Essa capítulo tem justamente essa finalidade, ou seja, de exibir o que o .NET Framework é capaz de fazer para atender essa necessidade que, torna-se cada vez mais comum.
  • Capítulo 8 – Criptografia Criptografia de dados é um ponto muito importante nos mais diversos tipos de aplicações. Geralmente, em aplicações onde alguns dos dados são muito sigilosos, como é o caso de aplicações financeiras, quais mantém os dados de seus clientes, é necessário que se mantenha esses dados seguros pois, se esses dados cairem em mãos erradas, essas pessoas com más intenções, não consigam entender e/ou recuperar esses dados em sua forma legível. Esse capítulo abordará extensamente as classes responsáveis por criptografia e hashing que o .NET Framework disponiliza, bem como utilizá-las e como aplicá-las ao dia-à-dia.
  • Capítulo 9 – Utilizando Code Access Security – CAS Toda aplicação que utiliza o Common Language Runtime (CLR) obrigatoriamente deve interagir com o sistema de segurança do mesmo. Quando a aplicação é executada, automaticamente é avaliado se ela tem ou não determinados privilégios. Dependendo das permissões que a aplicação tem, ela poderá rodar perfeitamente ou gerar erros relacionados a segurança. Code Access Security (também conhecido como CAS), é um mecanismo que ajuda limitar/conceder o acesso que o código que está querendo realizar, protegendo recursos e operações. Este capítulo abordará como utilizar o CAS, que é fornecido juntamente com o SDK do .NET Framework e, como configurar devidamente a aplicação para evitar problemas relacionados a segurança.
  • Capítulo 10 – Envio de Mensagens (E-mails) Envio de e-mails é muito comum em qualquer tipo de aplicação, seja ela uma aplicação para internet, uma aplicação para Windows ou até mesmo serviços que rodam sem uma intervenção do usuário. O .NET Framework fornece um namespace contendo classes e muitos outros tipos que podemos utilizar nas aplicação para habilitar o envio de e-mails e, conseqüentemente, torná-las muito mais dinâmicas e inteligentes.
  • Capítulo 11 – Criando Serviços do Windows Os Serviços do Windows (Windows Services), permitem-nos criar aplicações que rodam em “background” no sistema operacional. Estes serviços podem ser automaticamente inicializados quando o sistema operacional inicializar, podendo ainda ser pausado e reinicializado, sem apresentar nenhuma interface com o usuário. Esses serviços são ideais para ser usado em servidores ou em funcionalidades de longa duração que necessitem ser executadas de forma totalmente independente, sem a intervenção de um usuário. O capítulo corrente abordará desde a sua criação, depuração e instalação do mesmo.
  • Capítulo 12 – Interoperabilidade com componentes COM A Microsoft criou a plataforma .NET e, em pouco tempo, essa plataforma foi adotada por muitas e muitas empresas. Algo importante é que muitas dessas empresas, já tinham componentes COM que eram utilizados em massa nas aplicações e que são inviáveis para serem reescritos imediatamente. Felizmente a Microsoft pensou no legado e possibilita a interoperabilidade de componentes COM, interagindo com aplicações baseadas na plataforma .NET e vice-versa. Este capítulo mostrará os passos necessários para efetuar essa interoperabilidade entre as novas aplicações e o que já existe em código legado.
  • Capítulo 13 – Reflection Reflection é a habilidade de extrair informações de metadados de um determinado tipo, ou seja, quais parâmetros, métodos, entre outros membros um determinado tipo possui. Isso torna a aplicação bastante flexível, onde podemos extrair informações necessárias para podermos customizar e automatizar a criação de ferramentas e utilitários que auxiliam os próprios desenvolvedores. Além disso, permite a criação em runtime de Assemblies e como instanciar classes via programação. Esse capítulo propõe-se a explicar como criar esse tipo de funcionalidade dentro da aplicação.
  • Capítulo 14 – Threading A criação de threads permitem aumentar consideravelmente a performance das aplicações. Elas fornecem a habilidade de conseguirmos delegar processamentos em diversas unidades de execução, aumentando a capacidade de processamento de uma aplicação. Mas utilizando isso de forma errada, poderá piorar ao invés de melhorar, consumindo mais recursos do que o necessário, tendo um comportamento inesperado e retornando valores diferentes do esperado. O .NET Framework fornece várias classes que podemos utilizar para criação e gerenciamento de threads, bloqueio de recursos em um ambiente multi-threading e sincronização. Este capítulo irá ajudá-lo a conhecer alguns problemas existentes em aplicações que fazem o uso de threads e como contorná-los.

Referências Bibliográficas

  • Code Complete – Second Edition
    Autor: Steve McConnell
    Editora: Microsoft Press
    ISBN: 0-7356-1967-0
  • Writing Secure Code – Second Edition
    Autores: Michael Howard e David LeBlanc
    Editora: Microsoft Press
    ISBN: 0-7356-1722-8
  • CLR via C# – Second Edition
    Autor: Jeffrey Richter
    Editora: Microsoft Press
    ISBN: 0-7356-2163-2
  • Programming Visual C# 2005: The Language
    Autor: Donis Marshall
    Editora Microsoft Press
    ISBN: 0-7356-2181-0
  • Expressões Regulares – Uma abordagem divertida
    Autor: Aurélio Marinho Jargas
    Editora: Novatec
    ISBN: 85-7522-100-0
  • Collection 5160: Core Development with Microsoft .NET Framework 2.0
    Autor/Editor: Microsoft
  • Collection 5161: Advanced Development with Microsoft .NET Framework 2.0
    Autor/Editor: Microsoft

Gerando chaves para os atributos validationKey e decryptionKey

Como comentei no post anterior, precisamos ter uma chave única para que seja possível sincronizar os algoritmos de criptografia que o ASP.NET utiliza. Sendo assim, é necessário criar estas chaves e espeficá-las no arquivo Web.Config, como é mostrado abaixo:

<?xml version=”1.0″?>
<configuration>
  <system.web>
    <machineKey
        validationKey=”73…7B”
        decryptionKey=”CF…3B”
        validation=”SHA1″
        decryption=”AES” />
  </system.web>
</configuration>

Uma classe para auxiliar na geração destas chaves está aqui. É importante dizer que está seção é extremamente sensível, o que obriga voce a manter essas informações fora do alcance de todos.

Protegendo a seção machineKey

Uma vez que voce customiza a seção machineKey no arquivo Web.Config, é importante que as informações que nela constam sejam protegidas para que as chaves não caiam em mãos erradas.

Como sabem, o utilitário aspnet_regiis.exe permite-nos encriptar seções do arquivo Web.Config e, a aplicação irá trabalhar de forma transparente, sendo inteligente o bastante para saber se a mesma está ou não criptografa e, quando estiver, aplicará o algoritmo correto para recuperar os respectivos valores. A sintaxe para encriptar esta seção é simples:

C:>aspnet_regiis -pef system.web/machineKey “C:ExtraindoPasswordMembership” -prov “DataProtectionConfigurationProvider”

No atributo -pef informamos a seção do arquivo que queremos encriptar incluindo o caminho físico até a pasta que consta o arquivo Web.Config e, através do atributo -prov, informamos qual será o provider de criptografia a ser utilizado pelo utilitário. O resultado fica algo como:

<?xml version=”1.0″?>
<configuration>
  <system.web>
    <machineKey configProtectionProvider=”DataProtectionConfigurationProvider”>
      <EncryptedData>
        <CipherData>
          <CipherValue>AQAAANCMn….+m2p8oLI=</CipherValue>
        </CipherData>
      </EncryptedData>
    </machineKey>
  </system.web>
</configuration>

Recuperando Senhas através do Membership

A API do Membership permite-nos definir qual será o formato da senha que a mesma irá manipular. Voce pode configurar isso através da propriedade passwordFormat no arquivo Web.Config. Esse atributo recebe um dos tres valores abaixo:

  • Clear: As senhas não são criptografadas.
  • Encrypted: Senhas são criptografadas usando as configurações especificadas no elemento de configuração machineKey.
  • Hashed: As senhas são criptografadas utilizando o algoritmo de hash SHA1.

Quando optamos pelo formato Encrypted, há um passo adicional para que isso funcione. Há uma seção no arquivo de configuração chamada machineKey, que é responsável por armazenar informações relacionadas a criptografia de cookies, ViewState, etc.. Em sua configuração padrão, o ASP.NET utiliza chaves geradas automaticamente para aplicar ao algoritmo de criptografia. Esse comportamento impede o funcionamento da extração/definição da senha através do Membership em seu formato Encrypted. Se voce chegar até o método protegido EncryptPassword da classe MembershipProvider, verá que há essa consistencia:

protected virtual byte[] EncryptPassword(byte[] password)
{
    if (MachineKeySection.IsDecryptionKeyAutogenerated)
    {
        throw new ProviderException(SR.GetString(“Can_not_use_encrypted_passwords_with_autogen_keys”));
    }
    return MachineKeySection.EncryptOrDecryptData(true, password, null, 0, password.Length);
}

… e isso irá atirar a seguinte exceção:

You must specify a non-autogenerated machine key to store passwords in the encrypted format. Either specify a different passwordFormat, or change the machineKey configuration to use a non-autogenerated decryption key. 

Como voce tem a aplicação sendo executada em uma máquina A e move para uma máquina B, as senhas não serão mais válidas, já que as chaves são diferentes (se for a configuração padrão do ASP.NET). Devido a isso, voce precisará especificar uma chave única para o atributo validationKey e decryptionKey no arquivo Web.Config da aplicação ou no machine.Config caso queira isso para todas as aplicações. Para definir essas chaves, voce poderá utilizar o código abaixo no seu arquivo Web.Config:

<?xml version=”1.0″?>
<configuration>
  <system.web>
    <machineKey
      validationKey= “95…23”
      decryptionKey=”C7…BD”

      validation=”SHA1″
      decryption=”AES”/>
  </system.web>
</configuration>