Eu estava validando a arquitetura para uma prova de conceito que envolve o uso de Web Services utilizando um canal seguro de comunicação. Existem soluções antigas para esse problema, como a habilitação do uso de SSL na configuração do serviço no IIS, além de soluções in-house para criptografia de mensagens e passagem de tokens de autenticação (ex.: login/senha) no cabeçalho das mensagens SOAP. Essas soluções, apesar de funcionarem, apresentam algumas limitações:
- SSL é um protocolo que atua ponto a ponto, e não fim a fim. Isso significa que, havendo intermediários na comunicação cliente-servidor, a mensagem criptografada tem que ser descriptografada no intermediário, uma vez que uma nova seção SSL deve ser aberta a cada par de máquinas que se comuniquem. Essa nova seção exigirá uma nova criptografia da mensagem, todo um processo de handshaking, etc. Chamamos essa abordagem de "segurança a nível de transporte". Nela, a segurança é totalmente delegada para o sistema operacional, havendo aí uma dependência de plataforma (apesar de que várias plataformas hoje em dia suportam SSL)
- o uso de soluções in-house claramente apresenta problemas de interoperabilidade, uma vez que cada organização estará adicionando seus próprios headers, implementando suas próprias políticas "from scratch".
Para solucionar os problemas acima, foi definido um conjunto de padrões: WS-*. São vários padrões que se unem aos padrões já existentes para web services (SOAP, UDDI, etc.) para solucionar não apenas questões de segurança (autenticação, autorização, confidencialidade e integridade) mas também transações distribuídas, roteamento, envio de anexos binários, entre outros. O WS-Security trata especificamente da parte de segurança, e implementa a chamada "segurança a nível de mensagem", o que significa que mensagem XML original é criptografada, com a flexibilidade de apenas partes dela poderem ser criptografadas, e tokens de autenticação são automaticamente anexados e criptografados, de forma transparente para o desenvolvedor. Com isso não há nenhuma dependência em relação a plataforma.
A implementação MS para esses padrões é o Web Services Enhancements, ou WSE, que já está na sua versão 3.0. Esse não é um produto novo, mas só agora tive a oportunidade de avaliá-lo em um cenário real. O legal é que ele interopera com o Windows Communication Foundation.
A explicação abaixo está desatualizada em relação às maiores facilidades que o Windows Communication Foundation (WCF) fornece para segurança de Web Services, mas são úteis caso você precise rapidamente implementar segurança em seus web services e ainda não tiver um domínio a cerca das novas features do .NET 3.0, ou mesmo se não estiver planejando migrar código já existente para usar o WCF.
A título de exemplo da implementação de uma política de segurança para um web service, em geral são necessários poucos passos:
Após instalar o WSE 3.0, automaticamente o plug-in para o Visual Studio é instalado. Dessa forma, para habilitar o WSE em um web service, basta selecionar com o botão direito do mouse o projeto onde está o web service e clicar em WSE 3.0 Settings. A seguinte janela aparecerá:

Os check boxes exibidos devem ser marcados para que o WSE seja habilitado no projeto em questão.
Vamos passar agora à definição de uma política de segurança. Embora seja possível implementar políticas customizadas, o WSE já vem com um suporte pré-configurado a cenários comuns, a saber: autenticação com login/senha, certificado X.509, segurança integrada do Windows (autenticação via Kerberos), etc. Vamor ver, por exemplo, o passo-a-passo para definir uma política com autenticação baseada em login/senha, com criptografia e assinatura digital das mensagens trafegadas.
Na aba Security, escolha as opções "Enable Policy" e "Add" em "Edit Application Policy":

O wizard de definição de política entra em cena, após ser solicitado que se digite um nome para a política. Na primeira tela de configuração, é possível escolher se a política que está sendo definida é para um serviço ou para um cliente. No nosso exemplo, estamos configurando a segurança de um serviço. Ao mesmo tempo, podemos escolher o modo de autenticação desejado.

Também é possível definir já as políticas de autorização. Basicamente, nomes de papéis e usuários são gerados no arquivo de polítca que será criado ao fim da execução do wizard (embora essa não seja uma opção muito segura - o ideal é que a sua aplicação faça uso de uma base de usuários e papéis).

Um passo bem importante é a definição do nível de proteção que se deseja. Particularmente, quando estamos trabalhando com autenticação do tipo UsernameToken (login/senha), ao escolhermos a opção None, o WSE assume que a mensagem será protegida por SSL. Observação: o uso do SSL não é forçado pelo WSE. Nesse caso, você precisa configurar seu web service para usar a segurança a nível de transporte.

Finalmente, é solicitado que se especifique qual certificado será utilizado para a parte de criptografia e assinatura digital. Certificados digitais em geral contém duas chaves: uma pública, usada para criptografar a chave simétrica que será utilizada na criptografia e descriptografia das mensagens, e uma chave privada, conhecida apenas por aquele que receberá a mesagem, e que será responsável por descriptografar a chave simétrica. Essa é a base de funcionamento dos certiciados X.509, por exemplo. Essa é na realidade uma descrição auto-nível: a criptografia e assinatura digital de mensagens envolve um processo um pouco mais complicado de intercâmbio de chaves derivadas, quando utilizamos autenticação com login/senha. Chaves derivadas são, como o próprio nome diz, "derivadas" a partir da senha do cliente, e são elas as chaves simétricas a serem utilizadas nos mecanismos de criptografia e assinatura digital (no caso de assinaturas digitais, o hash da mensagem é que é criptografado).

Ao fim do processo, uma tela de confirmação é exibida com as opçoes que você escolheu, e o wizard pode ser finalizado. Para usar a política, base usar o atributo [Policy("nome da política")] na classe do web service, depois de adicionar a referência à DLL Microsoft.Web.Services3. Caso os seus clientes também estejam utilizando WSE, eles também em geral seguirão um processo análogo para a habilitação do WSE (quando um proxy WSE será gerado) e definição da política de segurança. Para usar a política, é só chamar SetPolicy("nome da política") no proxy. Adicionalmente, pode ser necessário chamar métodos para anexar tokens de autenticação, dependendo de como a política foi configurada. Todo esse processo está bem documentado nos manuais e demos que vêm com o WSE. No caso dos clientes, é necessário que eles adquiram previamente uma cópia da parte pública do certificado do servidor. O WSE não suporta a obtenção dinâmica do certificado, tal qual ocorre no SSL. Um detalhe importante: o WSE vem com certificados digitais de teste, cujas instruções de instalação são incluídas na própria documentação. Mas para que esses certificados possam ser usados, é necessário que a opção "Allow test roots" tanto no servidor como no cliente. Também é importante lembrar que esses certificados não devem ser usados em ambiente de produção, tanto por questões de segurança como de performance.

Antes de finalizar este post, uma dica: o guia que está disponível para download em http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag2/html/wssp.asp.