Entendendo Especificações de Serviços da Web, Parte 4: WS-Security

Há poucos (se algum) sistemas de nível corporativo que não requerem uma ou outra forma se segurança. Em serviços da Web, esse processo é mais complicado do que em outras áreas devido à sua natureza stateless distribuída. Este tutorial, Parte 4 da série Entendendo as Especificações de Serviços da Web, explica os conceitos por trás de WS-Security e padrões relacionados, como Assinatura XML, que se combinam para tornar a segurança no mundo de serviços da Web não apenas possível, mas prático.

Nicholas Chase, Freelance writer, Backstop Media

Nicholas Chase esteve envolvido no desenvolvimento de Web sites para empresas como a Lucent Technologies, a Sun Microsystems, a Oracle e a Tampa Bay Buccaneers. Nick foi professor de física para turmas de ensino médio, gerente de instalação de resíduos radioativos de nível inferior, editor de revista de ficção científica on-line, engenheiro de multimídia, instrutor de Oracle e Chief Technology Officer de uma empresa de comunicações interativas. Ele é autor de diversos livros, incluindo XML Primer Plus (Sam's).



16/Set/2011

Antes de iniciar

Neste tutorial, você aprenderá sobre Segurança de Serviços da Web, ou WS-Security. É para desenvolvedores que desejam expor seus próprios serviços em um ambiente que requeira proteção de mensagens para que não sejam violadas ou lidas em trânsito ou em situações em que o remetente deve ser positivamente identificado. O termo "WS-Security" é geralmente usado para fazer referência a um grupo de especificações que manipulam criptografia e assinaturas digitais, permitindo a criação de um aplicativo seguro.

Para acompanhar este tutorial, você deve ter um entendimento básico de SOAP, o que pode ser obtido com a leitura da Parte 1 desta série de tutoriais e, como extensão, você precisa de um entendimento básico de XML. SOAP é agnóstico com relação a linguagem de programação, mas as amostras deste tutorial usam Java™ e o projeto Apache Axis2. Os conceitos, no entanto, se aplicam a qualquer linguagem de programação e ambiente.

Sobre esta série

Esta série de tutoriais ensina os conceitos básicos de serviços da Web seguindo as explorações do jornal fictício, The Daily Moon, à medida que a equipe usar serviços d Web para criar um sistema de fluxo de trabalho para aumentar a produtividade no meio de muita mudança.

A Parte 1 explicou os conceitos básicos por trás de serviços da Web e mostrou como usar SOAP, a especificação subjacente à maior parte do que está por vir, conectando o departamento de classificados ao Sistema de Gerenciamento de Conteúdo.

A Parte 2 leva as coisas um passo adiante, explicando como usar Web Services Description Language (WSDL) para definir as mensagens produzidas conforme esperado por serviços da Web, permitindo que a equipe crie serviços mais facilmente e os clientes que conectam a eles.

A Parte 3 encontra a equipe com diversos serviços em vigor e deseja localizá-los facilmente. Em resposta, Universal Description, Discovery and Integration (UDDI) fornece um registro pesquisável de serviços disponíveis como uma maneira de divulgar seus próprios serviços a outros.

Agora, na Parte 4, Rudy, editor do The Daily Moon, decidiu que o jornal precisa instituir melhores procedimentos de segurança para serviços da Web que acessam seus sistemas internos.

Na Parte 5, WS-Policy, vamos ver as mudanças que as equipes precisam fazer para acessarem aqueles novos serviços protegidos.

Interoperabilidade será a palavra-chave na Parte 6, já que serviços de diversas implementações diferentes devem ser acessados a partir de um único sistema. A Parte 6 também abordará os requisitos e testes envolvidos na certificação WS-I.

Por fim, a Parte 7 mostrará como usar Business Process Execution Language (WS-BPEL) para criar aplicativos complexos a partir de serviços individuais.

Agora vamos dar uma olhada no que este tutorial aborda em pouco mais de detalhes.

Sobre este tutorial

Neste tutorial, você acompanhará à medida que a equipe do jornal The Daily Moon usa as especificações WS-Security para proteger um dos serviços da Web descritos até agora na série.

No curso deste tutorial, você aprenderá:

  • O que é WS-Security
  • As diferenças entre criptografia simétrica e assimétrica
  • As diferenças entre assinaturas e criptografia
  • O efeito de segurança em mensagens SOAP
  • Como proteger um serviço da Web SOAP usando Axis2

Antes de iniciar, algumas ferramentas serão necessárias.

Pré-requisitos

A maior parte deste tutorial é conceitual, mas para acompanhar o código que cria as mensagens SOAP, será necessário ter o software a seguir disponível e instalado:

Vamos demonstrar a instalação e uso do Apache Geronimo, que também é a base do WebSphere Community Edition da IBM. Também é possível usar outros servidores de aplicativos, como o WebSphere Application Server. É possível fazer download do Apache Geronimo. Para obter informações adicionais sobre como instalar o Geronimo, consulte Parte 1, desta série de tutoriais.

Você irá usar o Apache Axis2, que contém implementações de várias APIs relacionadas a SOAP para tornar sua vida significativamente mais fácil. É possível fazer download do Apache Axis2 a partir de Apache.org. Este tutorial usa a versão 0.94, mas versões posteriores devem funcionar.

Módulo Rampart do Apache Axis2 -- Segurança para o mecanismo de serviços da Web do Axis2 é fornecida por meio do módulo Rampart, que não está incluído na instalação padrão. Faça download desse módulo a partir de Apache Download Mirrors.

Apache WSS4J -- Apesar de o próprio Axis usar o Rampart, em algum ponto será necessário fazer referência à direção de classes WSS4J. Faça download de pacote WSS4J.

Java 2 Standard Edition versão 1.4.2 ou superior -- Todas essas ferramentas são baseadas em Java, assim como os serviços e clientes que você criará neste tutorial. Faça download de J2SE SDK.

TCPMon (opcional) -- Sempre é mais fácil entender o que está acontecendo em um aplicativo de serviço da Web quando é realmente possível ver as mensagens. Faça download de TCP Monitor para que possa ver as mensagens vindo e indo para o serviço da Web.

GnuPG (opcional) -- Toda a assinatura de mensagem que estaremos realizando é coberta pelo Axis2 e pelo próprio Java, mas se quiser brincar com assinatura de documentos individuais, como iremos demonstrar resumidamente, faça download de GnuPG.

Também serão necessários um navegador da Web e um editor de texto


Visão Geral

Antes de falarmos sobre como proteger um serviço, é útil saber exatamente quais são as partes que formam esse serviço para saber o que precisar ser feito.

A história até agora

Esta série de tutoriais as explorações da equipe do jornal The Daily Moon, que descobriu uma nova maneira de trabalhar na forma de serviços da Web. Tudo começou no departamento de classificados, que decidiu permitir que outros acessassem seus sistemas por meio do uso de mensagens SOAP -- mensagens XML que podem ser enviadas por HTTP.

Por exemplo, uma solicitação para o número de anúncios classificados na subcategoria "à venda" pode ter a aparência da Listagem 1.

Listagem 1. Uma mensagem SOAP de amostra
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
 <env:Header>
 </env:Header>
 <env:Body>
  <cms:getNumberOfArticles xmlns:cms="http://www.daily-moon.com/cms">
    <cms:category>classifieds</cms:category>
    <cms:subcategory>forsale</cms:subcategory>
  </cms:getNumberOfArticles>
 </env:Body>
</env:Envelope>

A mensagem geral é chamada de Envelope, o conteúdo do qual consiste em Cabeçalho e Corpo. O Cabeçalho contém informações sobre a própria mensagem, como informações de roteamento, informações que devem ser processadas por "intermediários SOAP" ou serviços entre o remetente e o destinatário final, que pode processar a mensagem. (Neste caso, consulte qualquer um desses cabeçalhos, mas é lá que nossas informações de segurança estarão.) O Corpo da mensagem inclui a "carga útil", que inclui os dados em si a serem passados ao serviço da Web.

Neste caso, a carga útil é o elemento getNumberOfArticles e seu conteúdo.

Gene e Frances, do departamento de TI do jornal, criaram um sistema para atender solicitações de serviços da Web, assim como a infraestrutura para descobrir e criar clientes automaticamente para os serviços. Agora o editor do jornal, Rudy, está insistindo para que encontrem uma maneira de evitar acesso não autorizado a esses sistemas.

A necessidade de segurança

A especificação SOAP básica não prevê a proteção de mensagens, deixando essa tarefa para especificações estendidas. O problema está na natureza de um aplicativo de serviços da Web. Na maioria dos casos, estamos lidando com SOAP sobre HTTP, o que significa que cada mensagem precisa viajar por um ou mais nós, qualquer um dos quais podendo ler e/ou alterar uma mensagem. E isso é supondo que a solicitação SOAP em si foi direta. Em alguns casos, as mensagens SOAP são projetadas especificamente para viajar por meio de mais de um nó antes de chegar a seu destino final.

O resultado final é que precisamos de uma maneira para evitar que alguém além do destinatário desejado leia as informações sigilosas, para evitar escuta. Também precisamos de uma maneira para evitar que alguém além do remetente desejado envie as mensagens para evitar acesso não autorizado.

A especificação SOAP fornece um meio para incluir informações de segurança -- incluímos informações em um elemento Cabeçalho do Envelope -- mas não especifica quais deveriam ser essas informações. Para cuidar disso, precisamos de WS-Security.

As partes de WS-Security

Há três problemas principais envolvidos a proteção de trocas de mensagens SOAP e WS-Security fornece respostas a todos eles, mas não diretamente. É, na verdade, uma especificação que fala não sobre como proteger a mensagem, mas como informar o remetente como você protegeu a mensagem. Para realizar a proteção em si, WS-Security faz referência a especificações adicionais. Vamos ver como isso funciona.

O primeiro problema é identificar e autenticar o cliente. Como há diversas maneiras diferentes para criar tokens de segurança, WS-Security não especifica nenhum meio específico, mas define como diferentes tokens de segurança devem ser transferidos dentro de mensagens SOAP. Em outras palavras, permite que o destinatário saiba como extrair tokens de segurança da mensagem para processamento.

O segundo problema é assegurar integridade da mensagem. WS-Security usa assinaturas digitais para isso, empregando a especificação Assinatura XML em vez de inventar algo novo. Assinatura XML é uma recomendação do W3C que fornece um mecanismo para assinar documentos XML digitalmente.

O terceiro problema é manter a mensagem segura contra escuta enquanto está em trânsito. Mais uma vez, WS-Security emprega outro padrão do W3C, desta vez, a Criptografia XML, que fornece um mecanismo para criptografar documentos XML.

Neste tutorial, vamos ver como o uso desses padrões afeta as mensagens SOAP em si usadas, à medida que Gene e Frances trabalham para proteger o serviço de Classificados existente.

O serviço atual

Antes de pensar em fazer mudanças, é útil ver de onde Gene e Frances estão começando. O serviço de Classificados está implementado usando o Axis2, o que significa que está contido em um arquivo *.aar. O arquivo CMSService.aar consiste em três arquivos, conforme mostrado na Listagem 2.

Listagem 2. O conteúdo do serviço original
CMSService.class
meta-inf/Manifest.MF

meta-inf/services.xml

A classe em si é direta, recebendo uma mensagem SOAP que lista uma categoria e retornando uma mensagem SOAP que inclui o número de anúncios para aquela categoria. Ela executa essa função conforme definido pelo arquivo services.xml (consulte Listagem 3).

Listagem 3. O arquivo services.xml original
<service name="CMSService">

    <description>
        This is a sample web service for the newspaper's 
        Content Managment System.
    </description>

    <parameter name="ServiceClass" 
               locked="false">CMSService</parameter>

    <operation name="getNumberOfArticles">
        <messageReceiver class=
"org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
    </operation>

</service>

A proteção do serviço envolve tocar somente o arquivo services.xml; Gene e Frances não precisarão tocar a classe Java em si de forma alguma.

O cliente atual

O cliente em si é bastante direto e simplesmente faz e exibe a solicitação, conforme mostrado na Listagem 4:

Listagem 4. A classe do cliente original
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;

public class ClassifiedClient {
    private static EndpointReference targetEPR = 
           new EndpointReference(
               "http://localhost:8888/axis2/services/CMSService");

    public static OMElement getNumOfArticlesOMElement() {
        SOAPFactory fac = OMAbstractFactory.getSOAP12Factory();
        OMNamespace omNs = fac.createOMNamespace(
                "http://daily-moon.com/cms", "cms");
        OMElement method = fac.createOMElement("getNumberOfArticles",
                                                omNs);
        OMElement value = fac.createOMElement("category", omNs);
        value.addChild(fac.createOMText(value, "classifieds"));
        method.addChild(value);

        return method;
    }

    public static void main(String[] args) {
        try {
            OMElement payload = 
               ClassifiedClient.getNumOfArticlesOMElement();
  
            Options options = new Options();
            options.setTo(targetEPR);
            options.setTransportInProtocol(Constants.TRANSPORT_HTTP);

            ServiceClient sender = new ServiceClient();

            sender.setOptions(options);
            OMElement result = sender.sendReceive(payload);

            String response = result.getText();
            System.out.println("There are "+response+
                               " classifieds at the moment.");
        } catch (Exception e) { 
        	System.out.println(e.toString());
        }
    }
}

Observe que Gene alterou a porta do terminal para 8888, em vez de 8080, a porta na qual o Geronimo está atendendo. Ele fez isso para inserir uma etapa adicional, de forma que ele possa ver as mensagens indo e vindo.

Vendo as mensagens

Para ver as mensagens SOAP em si, faça download de TCPMon a partir de http://ws.apache.org/commons/tcpmon/download.cgi. (Sim, o Axis2 vem com SOAPMonitor, mas Gene descobriu, da forma mais difícil, que além da dificuldade para configurar as coisas, mostra o SOAP, mas não necessariamente as mensagens brutas, o que vamos querer ver especificamente.)

Após fazer download, descompacte o aplicativo e execute o arquivo tcpmon-1.0-bin\build\tcpmon.bat . Clique na guia Admin e crie um novo listener, conforme visto na Figura 1.

Figura 1. A guia Admin do TCPMon
A guia Admin do TCPMon

Escolha 8888 como a porta na qual atender e especifique 8080 como o ponto de destino para que TCPMon fique entre o cliente e o servidor. Clique em Add e, em seguida, clique na guia Port 8888. Clique na caixa de opção XML Format. Agora, quando Frances executar o cliente, Gene poderá ver a solicitação e a resposta, como na Figura 2.

Figura 2. A solicitação e resposta originais
A solicitação e resposta originais

Antes de seguir em frente, vamos dar uma olhada rápida nas mensagens em si para que possamos ver o que muda.

As mensagens

As mensagens em si são bem diretas. A solicitação, conforme visto a Listagem 5, simplesmente pede o número de anúncios classificados no sistema:

Listagem 5. A solicitação original
<?xml version='1.0' encoding='UTF-8'?>
   <soapenv:Envelope
 xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
      <soapenv:Header />
      <soapenv:Body>
         <cms:getNumberOfArticles 
                    xmlns:cms="http://daily-moon.com/cms">
            <cms:category>classifieds</cms:category>
         </cms:getNumberOfArticles>
      </soapenv:Body>
   </soapenv:Envelope>

A resposta é igualmente direta, como é possível ver na Listagem 6:

Listagem 6: A resposta original
<?xml version='1.0' encoding='UTF-8'?>
   <soapenv:Envelope xmlns:soapenv=
           "http://schemas.xmlsoap.org/soap/envelope/">
      <soapenv:Header />
      <soapenv:Body>
         <resp:numberOfArcticles 
               xmlns:resp="http://daily-moon.com/cms/"  
               xmlns:tns="http://ws.apache.org/axis2"
                            >42</resp:numberOfArcticles>
      </soapenv:Body>
   </soapenv:Envelope>

Em ambas as mensagens, Frances colocará informações adicionais no elemento Header para que o servidor (ou o cliente) processe.

No momento, qualquer pessoa pode enviar uma solicitação e obter uma resposta e isso é o que deixa Rudy nervoso. Ele quer que o serviço seja configurado de forma que somente usuários autorizados possam obter informações e, assim, que a concorrência não possa interceptar as informações. Rudy acredita que esse seja um bom sistema de prova de conceito. Ele, na verdade, está mais preocupado com sistemas mais complexos, como aqueles que incluem conteúdo ou acesso ao sistema de contabilidade. Mas os conceitos são os mesmos.

Para fornecer essa segurança, Gene e Frances precisam usar criptografia e sua tecnologia relacionada, assinaturas.


Criptografia e Assinaturas

A maior parte das medidas de segurança envolve uma forma ou outra forma de criptografia ou criptografia trabalhada em ma assinatura digital, portanto, antes de Frances deixar Gene começar a trabalhar com a configuração de segurança do serviço, ela quer assegurar que entendam com o que estão lidando.

Tipos de criptografia

Criptografia é um processo de obscurecer informações para torná-las ilegíveis sem conhecimento especial. A história já conheceu muitos tipos diferentes de criptografia. A criptografia moderna geralmente é uma sequência bem definida de transformações aplicadas a uma mensagem e alguma forma de "chave". O resultado é algo ilegível. Decriptografia é um processo reverso e também envolve uma chave, portanto, mantendo a chave secreta, pode-se ter uma certeza razoável de que mais ninguém poderá ler a mensagem criptografada. Os métodos de criptografia moderna podem ser classificados considerando se usam uma ou duas chaves.

Em um algoritmo de chave simétrica (por exemplo, DES), o remetente e o destinatário devem ter uma chave compartilhada configurada com antecedência e mantida secreta de todas as outras partes; o remetente usa essa chave para criptografia e o destinatário usa a mesma chave para decriptografia. Neste caso, a chave em si não é importante, exceto por precisar se conhecida pelas duas partes envolvidas e somente por essas duas partes.

Em um algoritmo de chave assimétrica (como RSA), há duas chaves separadas: uma chave pública é publicada e conhecida por pertencer a um indivíduo (ou organização) específico, enquanto que uma chave privada correspondente é mantida secreta. Uma mensagem criptografada pela chave pública pode ser decriptografada somente pela chave pública, portanto, qualquer pessoa pode enviar uma mensagem privada a um indivíduo específico. Mas o reverso também é verdadeiro, portanto, uma mensagem que pode ser decriptografada por uma chave pública individual deve ter sido enviada por esse indivíduo. Vamos ver como isso entra na jogada ao criptografar e assinar mensagens SOAP

.

Criptografando um arquivo

Gene decide iniciar vendo como o texto da mensagem em si é afetado pela criptografia. Ele começa com um arquivo de texto, msg.txt, que consiste em uma única linha, como pode ver na Listagem 7.

Listagem 7. O destino alvo
Hello, world!

Para tornar as coisas simples, ele usa o programa gratuito GnuPG, executando o comando mostrado na Listagem 8.

Listagem 8. O comando de criptografia
gpg.exe -c -a --cipher-algo 3DES msg.txt

Esse comando faz com que o programa use o algoritmo de chave simétrica 3DES para criptografar o arquivo. O programa pede passphrase, que Gene insere como "password" e, em seguida, produz o arquivo msg.txt.asc. É possível ver o conteúdo desse arquivo na Listagem 9.

Listagem 9. O arquivo criptografado
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1.4.2.2 (MingW32)

jA0EAgMCqFjZXeujyOJgySoKQ2qhpCpGERKpFn0iKms4kwjpI51BLcoTyH4p61YJ
kDAiRMbC6PfCBmg=
=G4EN
-----END PGP MESSAGE-----

Com certeza, ninguém adivinharia o texto original disso! Animado, Gene segue em frente para analisar a questão de assinaturas digitais.

Como assinaturas funcionam

As assinaturas digitais usam técnicas de criptografia, mas o propósito de assinar é diferente. Em vez de obscurecer a mensagem, a assinatura dá ao destinatário confiança em duas informações: o remetente da mensagem e a própria mensagem.

Funciona da seguinte forma. O remetente criptografa a mensagem com sua chave privada. Essa "assinatura" é então enviada ao destinatário, juntamente com a mensagem original. O destinatário tenta verificar a assinatura, o que significa decriptografar a assinatura com a chave pública do remetente e comparar os resultados à mensagem original. Se esse processo for bem-sucedido, o destinatário pode ter certeza de que somente o remetente pode ser o originador da mensagem, pois ninguém, exceto o remetente, tem sua chave privada. Além do mais, se a mensagem original tivesse sido alterada em trânsito, a assinatura decriptografada não corresponderia, portanto, verificação de assinatura bem-sucedida também significa que a mensagem não foi violada.

Geralmente, em vez de assinar a mensagem inteira, o remetente calcula uma "compilação" da mensagem (usando uma função hash criptográfica), assina isso e passa isso juntamente com a mensagem não criptografada. O destinatário calcula a compilação da mensagem recebida e compara isso à compilação decriptografada da assinatura. Isso fornece o mesmo efeito sem precisar essencialmente dobrar o tamanho de cada mensagem. (Também reduz o tempo de processamento e verifica as assinaturas.)

Assinando um arquivo

Encorajado, Gene decide ver isso em ação. Sua intenção é assinar digitalmente o arquivo msg.txt que havia criptografado anteriormente. Como facilita a assinatura de um arquivo, ele usará o mesmo software GnuPG, apesar de posteriormente ele usar uma técnica diferente para criar as chaves usadas pelo aplicativo real.

A primeira etapa é criar o par de chaves usando o comando da Listagem 10.

Listagem 10. Gerando um par de chaves
gpg.exe --gen-key

O programa faz muitas perguntas sobre a chave, como o nome de Gene, o e-mail, etc. Ele aceita os parâmetros padrão da chave (o algoritmo DSA e o comprimento da chave de 2048 bits) e fornece o nome "Jon Dow". Essa operação armazena as chaves em um arquivo keystore na pasta inicial de Gene.

Agora ele pode assinar a mensagem. Ele usa o comando mostrado na Listagem 11.

Listagem 11. Assinando o documento
gpg.exe --clearsign -u "Jon Dow" msg.txt

Desta vez, o programa pede a senha associada à chave privada de "Jon Dow", em seguida, produz o arquivo msg.txt.asc, conforme mostrado na Listagem 12.

Listagem 12. O documento assinado
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hello, world!
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (MingW32)

iD8DBQFEhftF06oTl3UESDQRArHsAJ0bE2qUEeVb5IDz4gQuRCgOes6v7gCfQhbJ
l356yO+YTkJUJZx4KoTTzok=
=ld3Y
-----END PGP SIGNATURE-----

A pessoa que recebe essa mensagem saberia decriptografar a assinatura usando a chave pública de "Jon Dow", efetuaria hash da mensagem Não criptografada (usando SHA1) e compararia as duas.

Agora que entendem como criptografia e assinaturas funcionam, Gene e Frances estão prontos para seguir adiante para proteger o serviço em si.


Protegendo o Serviço

A proteção do serviço envolve diversas etapas que devem ocorrer antes de a primeira mensagem segura poder ser enviada e enquanto nenhuma delas for específica da especificação WS-Security em si (em vez de do software que a equipe está usando para gerar as mensagens), essas etapas são cruciais e ocorrerão, de uma forma ou de outra, para qualquer instalação de WS-Security.

Gerando o keystore

Agira que já viu assinaturas e criptografia em ação, Gene precisa começar a preparar a instalação da própria equipe. Precisa começar criando o keystore, que incluirá todos os pares de chave privada/chave pública que possam ser necessários. Para fazer isso, ele usará o aplicativo keytool que é fornecido com o JDK.

Para criar uma nova chave e gerar um keystore, ele executa os comandos a seguir, conforme visto na Listagem 13.

Listagem 13. Criando um par de chaves e um keystore
>cd %JAVA_HOME%\bin
>keytool -genkey -keystore mykeys.jks -alias gene
Enter keystore password:  mykeystorepassword
What is your first and last name?
  [Unknown]:  Gene Telluride
What is the name of your organizational unit?
  [Unknown]:  Information Technologies
What is the name of your organization?
  [Unknown]:  The Daily Moon
What is the name of your City or Locality?
  [Unknown]:  New York
What is the name of your State or Province?
  [Unknown]:  NY
What is the two-letter country code for this unit?
  [Unknown]:  US
Is CN=Gene Telluride, OU=Information Technologies, O=The Daily Moon, 
L=New York, ST=NY, C=U
S correct?
  [no]:  yes

Enter key password for <gene>
        (RETURN if same as keystore password):  mypassword

A linha de comando indica que a ferramenta deve gerar um par de chaves e armazená-lo no arquivo mykeys.jks. O par de chaves tem um alias gene, que permite ser facilmente referido. Frances pode criar sua chave e armazená-la no mesmo arquivo, mykeys.jks.

Agora estão prontos para iniciar a proteção do serviço em si.

Ativação de segurança

A primeira etapa para incluir WS-Security no serviço é ativá-lo no servidor. O Apache Axis2, o mecanismo de serviços da Web no qual a equipe está executando seus serviços, é criado de maneira modular e o módulo de WS-Security é chamado Rampart (consulte Pré-requisitos para obter informações sobre o download). Após ter transferido o Rampart por download, coloque o arquivo rampart-1.0.mar no diretório modules da instalação do Axis. Por exemplo, a instalação de Gene tem a pasta modules em C:\SW\geronimo-1.0\config-store\32\war\WEB-INF\modules.

Em seguida, Gene precisa tornar esse módulo globalmente disponível, pois na "cadeia manipuladora" que funciona em segundo plano no Axis2, precisa estar engajado antes de a mensagem poder ser direcionada a um serviço específico. Reinicie o Geronimo e efetue login na página de administração do Axis2 em http://localhost:8080/axis2/axis2-admin/login. (O nome de usuário é admin e a senha é axis2.) Clique em Engage Module/For all services e selecione rampart-1.0. Clique em Engage, como é possível ver na Figura 3.

Figura 3. Engajando o módulo Rampart
Engajando o módulo Rampart

Também é possível engajar o módulo Rampart incluindo o mesmo no arquivo axis2.xml, como verá quando virmos como proteger o cliente.

Configurar segurança no serviço

Agora que a infraestrutura está em vigor, Frances pode começar a proteger o serviço em si. Primeiro, ela encerra o Geronimo, pois deseja atualizar o arquivo services.xml que está localizado no archive CMSService.aar. (Ela tem a opção de atualizar e refazer upload do serviço, mas ela optou por alterar o archive diretamente.) A instalação do jornal tem o arquivo *.aar no local C:\SW\geronimo-1.0\config-store\32\war\WEB-INF\services\CMSService.aar. ela atualiza o arquivo services.xml para requerer um registro de data e hora, conforme visto na Listagem 14.

Listagem 14. incluindo um registro de data e hora no serviço
<service name="CMSService">

    <description>
        This is a sample web service for the newspaper's 
        Content Managment System.
    </description>

    <parameter name="ServiceClass" 
               locked="false">CMSService</parameter>

    <parameter name="InflowSecurity">
       <action>
            <items>Timestamp</items>
       </action>
    </parameter>

    <parameter name="OutflowSecurity">
       <action>
            <items>Timestamp</items>
       </action>
    </parameter> 

    <operation name="getNumberOfArticles">
        <messageReceiver class=
         "org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
    </operation>

</service>

O Axis2 permite que Frances controle especificamente mensagens entrando e saindo do serviço. Neste caso, ela informou ao mecanismo de serviços da Web para requerer que as mensagens recebidas incluam um registro de data e hora e para incluir um registro de data e hora nas mensagens de saída retornadas ao cliente.

Em um momento, veremos o efeito que essa mudança tem nas mensagens passadas entre servidor e cliente, mas quando Frances tenta executar um teste,o TCPMon mostra que o servidor retorna um erro em vez de as informações esperadas, como é possível ver na Listagem 15.

Listagem 15. Cabeçalhos de segurança ausentes
<?xml version='1.0' encoding='UTF-8'?>
   <soapenv:Envelope 
         xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
         xmlns:wsa="http://www.w3.org/2005/08/addressing">
      <soapenv:Header>
         <wsa:ReplyTo>
            <wsa:Address>
              http://www.w3.org/2005/08/addressing/anonymous
            </wsa:Address>
         </wsa:ReplyTo>
         <wsa:MessageID>
            urn:uuid:1CA9E94A9C7FE9D5B311507328796251
         </wsa:MessageID>
         <wsa:Action>
            http://www.w3.org/2005/08/addressing/fault
         </wsa:Action>
      </soapenv:Header>
      <soapenv:Body>
         <soapenv:Fault>
            <faultcode>soapenv:Client</faultcode>
            <faultstring>WSDoAllReceiver: Request does not 
               contain required Security header</faultstring> 
            <detail>
               <Exception>org.apache.axis2.AxisFault: WSDoAllReceiver: 
                   Request does not contain required Security 
                   header
 at ...
               </Exception>
            </detail>
         </soapenv:Fault>
      </soapenv:Body>
   </soapenv:Envelope>

O que importa aqui é que Frances agora sabe que está funcionando; o mecanismo não aceitará mensagens a menos que estejam de acordo com a segurança que ela configurou para o serviço.

Agora ela pode seguir para o cliente.

Protegendo o cliente

De muitas maneiras, o cliente também é um servidor até certo ponto, pois também envia e recebe mensagens SOAP, portanto, não deve ser nenhuma surpresa que a primeira etapa de Frances para proteger o cliente é incluir o rampart-1.0.mar na instalação do cliente. Para fazer isso, ela primeiro cria um novo diretório <CLIENT_HOME>\axis-repo\modules, em que <CLIENT_HOME> é o diretório no qual o arquivo ClassifiedClient.class está localizado. Ela inclui então o arquivo rampart-1.0.mar nesse diretório. Ela também cria um segundo diretório, <CLIENT_HOME>\axis-repo\conf, no qual ela cria um novo arquivo, axis2.xml. O arquivo contém o código visto na Listagem 16.

Listagem 16. O arquivo axis2.xml original
<axisconfig name="AxisJava2.0">

    <!-- Engage the security module -->
    <module ref="ramart"/>
    

    <parameter name="OutflowSecurity">
      <action>
        <items>Timestamp</items>
      </action>
    </parameter>

<!--    <parameter name="InflowSecurity">
      <action>
        <items>Timestamp</items>
      </action>
    </parameter> --> 

    <!-- ================================================= -->
    <!-- Parameters -->
    <!-- ================================================= -->
    <parameter name="hotdeployment"
 locked="false">true</parameter>
    <parameter name="hotupdate" locked="false">false</parameter>
    <parameter name="enableMTOM" locked="false">true</parameter>
    <!-- Uncomment this to enable REST support -->
    <!--    <parameter name="enableREST"
 locked="false">true</parameter>-->


    <parameter name="userName" locked="false">admin</parameter>
    <parameter name="password" locked="false">axis2</parameter>

    <!-- ================================================= -->
    <!-- Message Receivers -->
    <!-- ================================================= -->
    <!--This is the Deafult Message Receiver for the system , 
if you want to have MessageReceivers for -->
    <!--all the other MEP implement it and add the correct entry 
to here, so that you can refer from-->
    <!--any operation -->
    <!--Note : You can ovride this for particular service by 
adding the same element with your requirement-->
    <messageReceivers>
        <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
                        
 class="org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver"/>
        <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
                        
 class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
    </messageReceivers>
    <!-- ================================================= -->
    <!-- Transport Ins -->
    <!-- ================================================= -->
    <transportReceiver name="http"
                      
 class="org.apache.axis2.transport.http.SimpleHTTPServer">
        <parameter name="port" locked="false">6060</parameter>
        <!--If you want to give your own host address for EPR
 generation-->
        <!--uncommet following paramter , and set as you required.-->
        <!--<parameter name="hostname"
 locked="false">http://myApp.com/ws</parameter>-->
    </transportReceiver>

    <transportReceiver name="tcp"
                       class="org.apache.axis2.transport.tcp.TCPServer">
        <parameter name="port" locked="false">6061</parameter>
        <!--If you want to give your own host address for EPR
 generation-->
        <!--uncommet following paramter , and set as you required.-->
        <!--<parameter name="hostname"
 locked="false">tcp://myApp.com/ws</parameter>-->
    </transportReceiver>

    <!-- ================================================= -->
    <!-- Transport Outs -->
    <!-- ================================================= -->

    <transportSender name="tcp"
                    
 class="org.apache.axis2.transport.tcp.TCPTransportSender"/>
    <transportSender name="local"
                    
 class="org.apache.axis2.transport.local.LocalTransportSender"/>
    <transportSender name="jms"
                     class="org.apache.axis2.transport.jms.JMSSender"/>
    <transportSender name="http"
                    
 class="org.apache.axis2.transport.http.CommonsHTTPTransportSender">
        <parameter name="PROTOCOL"
 locked="false">HTTP/1.1</parameter>
        <parameter name="Transfer-Encoding"
 locked="false">chunked</parameter>
    </transportSender>
    <transportSender name="https"
                    
 class="org.apache.axis2.transport.http.CommonsHTTPTransportSender">
        <parameter name="PROTOCOL"
 locked="false">HTTP/1.1</parameter>
        <parameter name="Transfer-Encoding"
 locked="false">chunked</parameter>
    </transportSender>

    <!-- ================================================= -->
    <!-- Phases  -->
    <!-- ================================================= -->
    <phaseOrder type="inflow">
        <!--  System pre defined phases       -->
         <phase name="Transport">
            <handler name="RequestURIBasedDispatcher"
                    
 class="org.apache.axis2.engine.RequestURIBasedDispatcher">
                <order phase="Dispatch"/>
            </handler>
            <handler name="SOAPActionBasedDispatcher"
                    
 class="org.apache.axis2.engine.SOAPActionBasedDispatcher">
                <order phase="Dispatch"/>
            </handler>
        </phase>
        <phase name="Security"/>
        <phase name="PreDispatch"/>
        <phase name="Dispatch"
 class="org.apache.axis2.engine.DispatchPhase">
            <handler name="AddressingBasedDispatcher"
                    
 class="org.apache.axis2.engine.AddressingBasedDispatcher">
                <order phase="Dispatch"/>
            </handler>

            <handler name="SOAPMessageBodyBasedDispatcher"
                    
 class="org.apache.axis2.engine.SOAPMessageBodyBasedDispatcher">
                <order phase="Dispatch"/>
            </handler>
            <handler name="InstanceDispatcher"
                     class="org.apache.axis2.engine.InstanceDispatcher">
                <order phase="PostDispatch"/>
            </handler>
        </phase>
        <!--  System pre defined phases       -->
        <!--   After Postdispatch phase module author or or 
service author can add any phase he want      -->
        <phase name="OperationInPhase"/>
    </phaseOrder>
    <phaseOrder type="outflow">
        <!--      user can add his own phases to this area  -->
        <phase name="OperationOutPhase"/>
        <!--system predefined phase-->
        <!--these phase will run irrespective of the service-->
        <phase name="PolicyDetermination"/>
        <phase name="MessageOut"/>
    </phaseOrder>
    <phaseOrder type="INfaultflow">
        <phase name="PreDispatch"/>
        <phase name="Dispatch"
 class="org.apache.axis2.engine.DispatchPhase">
            <handler name="RequestURIBasedDispatcher"
                    
 class="org.apache.axis2.engine.RequestURIBasedDispatcher">
                <order phase="Dispatch"/>
            </handler>

            <handler name="SOAPActionBasedDispatcher"
                    
 class="org.apache.axis2.engine.SOAPActionBasedDispatcher">
                <order phase="Dispatch"/>
            </handler>

            <handler name="AddressingBasedDispatcher"
                    
 class="org.apache.axis2.engine.AddressingBasedDispatcher">
                <order phase="Dispatch"/>
            </handler>

            <handler name="SOAPMessageBodyBasedDispatcher"
                    
 class="org.apache.axis2.engine.SOAPMessageBodyBasedDispatcher">
                <order phase="Dispatch"/>
            </handler>
            <handler name="InstanceDispatcher"
                     class="org.apache.axis2.engine.InstanceDispatcher">
                <order phase="PostDispatch"/>
            </handler>
        </phase>
        <!--      user can add his own phases to this area  -->
        <phase name="OperationInFaultPhase"/>
    </phaseOrder>
    <phaseOrder type="Outfaultflow">
        <!--      user can add his own phases to this area  -->
        <phase name="OperationOutFaultPhase"/>
        <phase name="PolicyDetermination"/>
        <phase name="MessageOut"/>
    </phaseOrder>
    </axisconfig>

A maior parte desse código é padrão, tomado emprestado de outros exemplos do Axis2. Na seção em negrito na parte superior, no entanto, Frances inclui para indicar ao cliente para incluir um registro de data e hora na mensagem que enviar ao servidor. Ela opta por não lidar com o registro de data e hora retornado pelo servidor, pelo menos por ora. Diferentemente do serviço, no entanto, o cliente não obedecerá automaticamente essas diretivas. Ela precisa fazer mudanças na própria classe.

Mudanças na classe do cliente

Para que a classe do cliente faça as mudanças especificadas no arquivo axis2.xml, ela precisa saber sobre elas. Por isso, Frances inclui a configuração no processo de criação de ServiceClient, conforme visto na Listagem 17.

Listagem 17. Chamando a nova configuração a partir de ClassifiedClient.java
...
    public static void main(String[] args) {
        try {
            OMElement payload = 
                ClassifiedClient.getNumOfArticlesOMElement();
            ConfigurationContext 
                 configContext = ConfigurationContextFactory
                      .createConfigurationContextFromFileSystem(
                                               "axis-repo", null); 
            Options options = new Options();
            options.setTo(targetEPR);
            options.setTransportInProtocol(Constants.TRANSPORT_HTTP);

            ServiceClient sender = 
                  new ServiceClient(configContext, null);

            sender.setOptions(options);
            OMElement result = sender.sendReceive(payload);

            String response = result.getText();
            System.out.println("There are "+response+
                                  " classifieds at the moment.");
        } catch (Exception e) { 
        	System.out.println(e.toString());
        }
    }
}

Primeiro, Frances cria um novo ConfigurationContext, que permite que ServiceClient procure uma nova configuração. Mas para fazer isso acontecer, ela precisará alterar a maneira como chama a classe do cliente em si.

Juntando tudo

Para que o cliente chame corretamente o módulo Rampart, ele precisa saber onde encontrar o arquivo de configuração e onde encontrar quaisquer outros itens de repositório, como o próprio arquivo *.mar. Para fazer isso, Frances inclui mais detalhes no script que configura seu caminho de classe e executa a classe do cliente, conforme visto na Listagem 18.

Listagem 18. Chamando a classe
echo off
SET CLASSPATH=C:/SW/axis2/lib/XmlSchema-1.0.2.jar
SET CLASSPATH=%CLASSPATH%;C:/SW/axis2/lib/axiom-api-1.0.jar
SET CLASSPATH=%CLASSPATH%;C:/SW/axis2/lib/axiom-impl-1.0.jar
SET CLASSPATH=%CLASSPATH%;C:/SW/axis2/lib/axis2-kernel-1.0.jar
SET CLASSPATH=%CLASSPATH%;C:/SW/axis2/lib/commons-codec-1.3.jar
SET CLASSPATH=%CLASSPATH%;C:/SW/axis2/lib/commons-httpclient-3.0.jar
SET CLASSPATH=%CLASSPATH%;C:/SW/axis2/lib/commons-logging-1.0.4.jar
SET CLASSPATH=%CLASSPATH%;C:/SW/axis2/lib/
                             geronimo-spec-activation-1.0.2-rc4.jar
SET CLASSPATH=%CLASSPATH%;C:/SW/axis2/lib/
                             geronimo-spec-javamail-1.3.1-rc5.jar
SET CLASSPATH=%CLASSPATH%;C:/SW/axis2/lib/jaxen-1.1-beta-8.jar
SET CLASSPATH=%CLASSPATH%;C:/SW/axis2/lib/log4j-1.2.13.jar
SET CLASSPATH=%CLASSPATH%;C:/SW/axis2/lib/neethi-1.0.1.jar
SET CLASSPATH=%CLASSPATH%;C:/SW/axis2/lib/stax-api-1.0.jar
SET CLASSPATH=%CLASSPATH%;C:/SW/axis2/lib/wsdl4j-1.5.2.jar
SET CLASSPATH=%CLASSPATH%;C:/SW/axis2/lib/wstx-asl-2.9.3.jar
SET CLASSPATH=%CLASSPATH%;C:/sw/ClassifiedClient/lib/wss4j-1.5.0.jar
SET CLASSPATH=%CLASSPATH%;C:/sw/ClassifiedClient/lib/xmlsec-1.3.0.jar
SET CLASSPATH=%CLASSPATH%;C:/sw/ClassifiedClient/lib/
                             commons-discovery-0.2.jar
SET CLASSPATH=%CLASSPATH%;C:/sw/ClassifiedClient/lib/
                             bcprov-jdk13-132.jar
SET CLASSPATH=%CLASSPATH%;C:/sw/ClassifiedClient/lib/xalan.jar
SET CLASSPATH=%CLASSPATH%;.

java.exe -Daxis2.xml=axis-repo/conf/axis2.xml 
         -Daxis2.repo=axis-repo ClassifiedClient

Observe que Frances também inclui diversos arquivos *.jar da distribuição WSS4J (consulte Pré-requisitos para obter informações sobre o download).

Agora ela está pronta para tentar a solicitação mais uma vez.

A solicitação

A execução da solicitação mostra uma mensagem SOAP normal, com uma exceção, conforme visto na Listagem 19.

Listagem 19. Uma mensagem SOAP com registro de data e hora
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv=
      "http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header>
      <wsse:Security xmlns:wsse="http://docs.oasis-
open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-
1.0.xsd" soapenv:mustUnderstand="1">
         <wsu:Timestamp xmlns:wsu="http://docs.oasis-
open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-
1.0.xsd" wsu:Id="Timestamp-29987161">
            <wsu:Created>2006-06-19T16:22:28.578Z</wsu:Created>
            <wsu:Expires>2006-06-19T16:27:28.578Z</wsu:Expires>
         </wsu:Timestamp>
      </wsse:Security> 
   </soapenv:Header>
   <soapenv:Body>
      <cms:getNumberOfArticles xmlns:cms="http://daily-moon.com/cms">
         <cms:category>classifieds</cms:category>
      </cms:getNumberOfArticles>
   </soapenv:Body>
</soapenv:Envelope>

Agora, pela primeira vez, Frances vê um cabeçalho de Segurança em suas mensagens. Neste caso, é apenas um registro de data e hora, que mostra quando a mensagem foi criada. O atributo mustUnderstand significa que se o servidor não souber o que fazer com esse elemento de registro de data e hora, ele deve rejeitar a mensagem.

Registros de data e hora são provavelmente o elemento mais simples de WS-Security. Eles fornecem uma maneira de limitar o tempo de vida das mensagens, evitando que rebeldes interceptem mensagens, alterando-as a seu bel-prazer, e enviando-as adiante. Neste caso, o registro de data e hora expira cinco segundos após a criação da mensagem, portanto, se a mensagem for mais antiga que isso, ela deve ser rejeitada. (Sim, um rebelde ainda pode alterar os valores de registro de data e hora, mas vamos lidar com isso quando chegarmos a assinaturas.)

A resposta

Conforme especificado no serviço, a resposta também tem um registro de data e hora, conforme visto na Listagem 20.

Listagem 20. A resposta
<?xml version='1.0' encoding='UTF-8'?>
   <soapenv:Envelope xmlns:soapenv=
            "http://schemas.xmlsoap.org/soap/envelope/">
      <soapenv:Header>
         <wsse:Security xmlns:wsse="http://docs.oasis-
open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-
1.0.xsd" soapenv:mustUnderstand="1">
            <wsu:Timestamp xmlns:wsu="http://docs.oasis-
open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-
1.0.xsd" wsu:Id="Timestamp-22347273">
              
 <wsu:Created>2006-06-19T16:22:29.281Z</wsu:Created>
              
 <wsu:Expires>2006-06-19T16:27:29.281Z</wsu:Expires>
            </wsu:Timestamp>
            <wsse11:SignatureConfirmation xmlns:wsse11=
"http://docs.oasis-open.org/wss/2005/xx/oasis-2005xx-wss-wssecurity-
secext-1.1.xsd" xmlns:wsu="http://docs.oasis-
open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-
1.0.xsd" wsu:Id="SigConf-5759024" />
         </wsse:Security> 
      </soapenv:Header>
      <soapenv:Body>
         <resp:numberOfArcticles 
                     xmlns:resp="http://daily-moon.com/cms/" 
                     xmlns:tns="http://ws.apache.org/axis2"
                >42</resp:numberOfArcticles>
      </soapenv:Body>
   </soapenv:Envelope>

A resposta inclui o registro de data e hora, conforme especificado, mas também mostra que as informações de segurança foram processadas e verificadas, mesmo sem que Frances tenha configurado o cliente para verificar qualquer um desses dois fatos.

Observe que em ambos os casos, as mensagens em si foram deixadas intactas.


Assinando Mensagens

Agora, neste ponto, Frances incluiu um registro de data e hora nas mensagens de saída e recebidas, mas não há nada para evitar que alguém simplesmente altere seu valor e retransmita a mesma. Para solucionar esse problema (e quaisquer outros problemas decorrentes de informações que possam ter sido alteradas), Frances precisa dar uma olhada em assinar suas mensagens.

Como funciona assinatura de mensagens

Como vimos anteriormente, assinar uma mensagem envolve a criação de uma versão dos dados que foram criptografados de maneira conhecida para que ao serem decriptografados seja fornecido um valor que possa ser comparado ao original. Por exemplo, digamos que Frances deseje assinar digitalmente o elemento de registro de data e hora em suas mensagens para que o servidor possa verificar se elas não foram violadas ou desviadas de alguma maneira.

para fazer isso, ela irá instituir um processo que levará diversas etapas.

Primeiro, ela assinará a mensagem (ou parte da mensagem). Para fazer isso, ela usará o arquivo axis2.xml para especificar um usuário como o assinante. O Axis2 pegará essas informações e fará duas coisas com elas. Primeiro, alimentará o alias do usuário para uma "classe de retorno de chamada", que retornará a senha para esse usuário. Armado com essa senha, o Axis2 irá recuperar então a chave privada desse usuário do keystore criado anteriormente.

Usando a chave privada, o Axis2 criptografa, ou assina, a parte relevante da mensagem e inclui a assinatura na mensagem. Ele então envia a mensagem. Quando o serviço recebe a mensagem, ele faz quase a mesma coisa; ele acessa o keystore para obter a chave pública desse usuário e, em seguida, verifica a assinatura.

Observe que se o serviço fosse enviar conteúdo de volta que foi assinado, essas funções seriam reservadas à viagem de volta.

Vamos dar uma olhada como configurar isso.

A classe callback

A primeira etapa é criar a classe callback . Em uma situação real, essa classe pode acessar um diretório do LDAP ou usar outros métodos para associar um nome de usuário a uma senha, mas Frances está começando com uma prova de conceito, então ela criará uma classe callback simples que retorna valores arbitrários, como é possível ver na Listagem 21.

Listagem 21. PWCallback.java, a classe callback
import org.apache.ws.security.WSPasswordCallback;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import java.io.IOException;

public class PWCallback implements CallbackHandler {

   public void handle(Callback[] callbacks)
            throws IOException, UnsupportedCallbackException {

      for (int i = 0; i < callbacks.length; i++) {
         if (callbacks[i] instanceof WSPasswordCallback) {
            WSPasswordCallback pc=(WSPasswordCallback)callbacks[i];
                if (pc.getIdentifer().equals("gene")) {
                    pc.setPassword("mypassword");
                } else if (pc.getIdentifer().equals("frances")) {
                    pc.setPassword("francespassword");
                } else {
                    throw new UnsupportedCallbackException(
                                   callbacks[i], "Unknown user");
                }
            } else {
                throw new UnsupportedCallbackException(callbacks[i],
                        "Unrecognized Callback");
            }
        }
    }
}

O que a classe faz no método handle() não é importante; tudo que importa é que configura a senha no objeto WSPasswordCallback ou emite uma exceção.

O arquivo de propriedades

Em seguida, Frances precisa encontrar uma maneira de informar o Axis2 onde localizar o keystore e qual classe deve realmente executar toda essa magia criptográfica. Para fazer isso, ela cria um arquivo de propriedades, security.properties, conforme visto na Listagem 22:

Listagem 22. O arquivo security.properties
org.apache.ws.security.crypto.provider=org.apache.ws.security.compo
nents.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=mykeystorepa
ssword
org.apache.ws.security.crypto.merlin.file=mykeys.jks

Após especificar o provedor, o arquivo de propriedades fornece o tipo de keystore -- neste caso, jks, o formato proprietário fornecido com Java -- a senha do keystore e o nome do arquivo do keystore em si, que por questão de simplificação ala coloca no mesmo diretório que o arquivo de classe do cliente.

O arquivo axis2.xml

Agora ela precisa passar ao arquivo axis2.xml o que ela tem em mente para as mensagens de saída, como é possível ver na Listagem 23.

Listagem 23. O arquivo axis2.xml, com assinatura
<axisconfig name="AxisJava2.0">

    <!-- Engage the security module -->
    <module ref="rampart"/>

    <parameter name="OutflowSecurity">
      <action>
        <items>Signature</items>
        <user>gene</user><passwordCallbackClass>PWCallback</passwordCallbackClass>
       
 <signaturePropFile>security.properties</signaturePropFile>
        <signatureKeyIdentifier>SKIKeyIdentifier</signatureK
eyIdentifier>
        <signatureParts>{Element}{http://schemas.xmlsoap.org
/soap/envelope/}Body</signatureParts>
      </action>
    </parameter>
<!--
    <parameter name="InflowSecurity">
      <action>
        <items>Timestamp</items>
      </action>
    </parameter>
-->
...

Neste caso, em vez de dizer para o cliente incluir um registro de data e hora, ela está dizendo para incluir uma assinatura. Vendo isso, o cliente consulta o arquivo especificado em signaturePropFile e usa as informações encontradas lá -- juntamente com passwordCallbackClass -- para obter a senha para o usuário gene. De lá, pega a chave privada de gene e assina somente a parte da mensagem especificada no elemento signatureParts . Neste caso, isso significa o elemento representado pelo Corpo (em oposição a apenas o conteúdo do elemento), que faz parte do namespace http://schemas.xmlsoap.org/soap/envelope/.

É possível assinar qualquer parte da mensagem. Por exemplo, as pessoas frequentemente assinam o registro de data e hora, se presente.

A solicitação

Então o que todas essas mudanças significam para as mensagens produzidas pelo cliente? É possível ver a solicitação resultante na Listagem 24.

Listagem 24. A solicitação assinada
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv=
        "http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header>
      <wsse:Security xmlns:wsse="..." soapenv:mustUnderstand="1">
         <ds:Signature xmlns:ds="..." Id="Signature-8789796">
            <ds:SignedInfo>
               <ds:CanonicalizationMethod Algorithm=
                    "http://www.w3.org/2001/10/xml-exc-c14n#" />
               <ds:SignatureMethod Algorithm=
                 "http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
               <ds:Reference URI="#id-17764792">
                  <ds:Transforms>
                     <ds:Transform Algorithm=
                    "http://www.w3.org/2001/10/xml-exc-c14n#" />
                  </ds:Transforms>
                  <ds:DigestMethod Algorithm=
                     "http://www.w3.org/2000/09/xmldsig#sha1" />
                  <ds:DigestValue
                  >wg+9KsR6BVBiO/hakJJwMdtU7+I=</ds:DigestValue>
               </ds:Reference>
            </ds:SignedInfo>

 <ds:SignatureValue>hom9Enzu3yHBuaF...</ds:SignatureValue>
            <ds:KeyInfo Id="KeyId-19475750">
               <wsse:SecurityTokenReference xmlns:wsu=".." 
                      wsu:Id="STRId-31156635">
                  <wsse:KeyIdentifier EncodingType="http://docs.oasis
-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-
1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/o
asis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier"
>CuJdE1B2dUFd1dkLZSzQ5vj6MYg=</wsse:KeyIdentifier>
               </wsse:SecurityTokenReference>
            </ds:KeyInfo>
         </ds:Signature>
      </wsse:Security>
   </soapenv:Header>
   <soapenv:Body xmlns:wsu="..." wsu:Id="id-17764792">
      <cms:getNumberOfArticles xmlns:cms="http://daily-moon.com/cms">
         <cms:category>classifieds</cms:category>
      </cms:getNumberOfArticles>
   </soapenv:Body>
</soapenv:Envelope>

Eu cortei fora valores de namespace para tornar isto um pouco mais legível, mas vamos passar por ele por partes. O elemento Security contém todas as informações de segurança, é claro, começando coma assinatura. A assinatura começa com as informações sobre o que realmente foi assinado. Seguindo adiante só um pouco, o elemento Reference inclui um atributo URI , que refere de volta ao atributo id do corpo, que é, lembre-se, o que Frances pediu para o cliente assinar. Então, isso indica ao serviço quais informações foram realmente assinadas.

Voltando, a primeira etapa para assinar o conteúdo é canonicalizá-lo -- remover nós de texto irrelevantes, etc. -- mas, na verdade, há duas maneiras de fazer isso, inclusiva e exclusiva, a diferença sendo como cada método manipula as declarações de namespace. Então o elemento CanonicalizationMethod especifica qual método é usado pela assinatura.

Vamos então para SignatureMethod, que especifica, como o nome sugere, o método usado para assinar os dados relevantes.

O elemento Reference inclui informações sobre todas as etapas que foram executadas para chegar no conteúdo final para assinar, em ordem, para que o processo de verificação possa levar as mesmas etapas e (esperamos) chegar ao mesmo SignatureValue.

KeyInfo fornece a chave em si usada para assinar os dados ou uma referência à chave.

Fazendo mudanças no serviço

Agora o cliente está criando a assinatura, mas o serviço não sabe o que fazer com ela. Frances está prestes a mudar isso.

Essencialmente, o serviço precisa executar muitas das mesmas etapas que o cliente executou; precisa poder localizar senhas e chaves no keystore, então Frances inicia incluindo os arquivos mykeys.jks, PWCallback.class e security.properties no arquivo CMSService.aar. Não é necessário usar a mesma classe e keystore usados para o cliente, mas, neste caso, ela o faz por questão de conveniência.

Ela também inclui bcprov-jdk13-132.jar, wss4j-1.5.0.jar e xmlsec-1.3.0.jar no diretório lib do aplicativo Axis2. (Esses arquivos vêm da distribuição WSS4J.)

Frances precisa então configurar a definição de serviço (em services.xml) para reconhecer que dados assinados estão vindo em sua direção. Ela faz isso realizando as mudanças mostradas na Listagem 25.

Listagem 25. Informando o servidor para esperar dados assinados
<service name="CMSService">

    <description>
   This is a sample web service for the newspaper's Content Managment System.
    </description>

    <parameter name="ServiceClass"
 locked="false">CMSService</parameter>

    <parameter name="InflowSecurity">
       <action>
            <items>Signature</items>
           
 <passwordCallbackClass>PWCallback</passwordCallbackClass>
           
 <signaturePropFile>security.properties</signaturePropFile>
       </action>
    </parameter>

    <parameter name="OutflowSecurity">
       <action>
            <items>Timestamp</items>
       </action>
    </parameter>

    <operation name="getNumberOfArticles">
        <messageReceiver
 class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
    </operation>

</service>

Essas mudanças são suficientes para deixar o serviço ciente do que deve esperar e o que fazer com os dados assinados.

A resposta

A resposta é um documento que inclui um registro de data e hora, conforme especificado no parâmetro OutFlowSecurity , mas também inclui informações sobre a verificação da assinatura, conforme visto na Listagem 26.

Listagem 26. A resposta
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv=
         "http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header>
      <wsse:Security xmlns:wsse="..." soapenv:mustUnderstand="1">
         <wsu:Timestamp xmlns:wsu="..." wsu:Id="Timestamp-27995990">
            <wsu:Created>2006-06-19T23:56:55.214Z</wsu:Created>
            <wsu:Expires>2006-06-20T00:01:55.214Z</wsu:Expires>
         </wsu:Timestamp>
         <wsse11:SignatureConfirmation xmlns:wsse11="..." 
             xmlns:wsu="..." Value="hom9Enzu3yHBuaigFl26b6A+5hy..." 
             wsu:Id="SigConf-25877728" />
      </wsse:Security>
   </soapenv:Header>
   <soapenv:Body>
      <resp:numberOfArcticles xmlns:resp="http://daily-moon.com/cms/" 
  
 xmlns:tns="http://ws.apache.org/axis2">42</resp:numberOfArcticles>
   </soapenv:Body>
</soapenv:Envelope>

Agora vamos dar uma olhada em incluir criptografia na figura.


Incluindo Criptografia

Frances está satisfeita com o processo de verificação de parte da mensagem usando assinaturas, mas ainda não há como obscurecer informações para que a concorrência e outros vilões não possam ler as mesmas. Para cuidar disso, será necessário incluir criptografia no aplicativo.

Alterando o serviço

Desta vez, ela começa com o serviço. Ela já incluiu todas as classes adicionais necessárias para o aplicativo, portanto, tudo que ela precisa alterar é o arquivo services.xml, como é possível ver na Listagem 27.

Listagem 27. Incluindo criptografia no serviço
<service name="CMSService">

    <description>
        This is a sample web service for the newspaper's 
        Content Managment System.
    </description>

    <parameter name="ServiceClass" 
               locked="false">CMSService</parameter>

    <parameter name="InflowSecurity">
       <action>
            <items>Timestamp Signature
 Encrypt</items>
           
 <passwordCallbackClass>PWCallback</passwordCallbackClass>
           
 <signaturePropFile>security.properties</signaturePropFile>
       </action>
    </parameter>

    <operation name="getNumberOfArticles">
        <messageReceiver class=
        "org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
    </operation>

</service>

Aqui, Frances indicou ao serviço que mensagens recebidas terão tido um registro de data e hora incluído, em seguida, terão sido assinadas e depois terão sido criptografadas -- nesta ordem.

Agora, ela apenas precisa dizer para o cliente fazer isso.

Alterando o cliente

Como ela já preparou a base, incluir criptografia no cliente também é direto e envolve apenas uma mudança simples no arquivo axis2.xml, como pode ver na Listagem 28.

Listagem 28. Incluindo criptografia no cliente
<axisconfig name="AxisJava2.0">

    <!-- Engage the security module -->
    <module ref="rampart"/>
    

    <parameter name="OutflowSecurity">
      <action>
        <items>Timestamp Signature Encrypt</items>
        <user>gene</user>
        <passwordCallbackClass>PWCallback</passwordCallbackClass>
       
 <signaturePropFile>security.properties</signaturePropFile>
        <signatureKeyIdentifier
                        >SKIKeyIdentifier</signatureKeyIdentifier>
        <encryptionKeyIdentifier
                       >SKIKeyIdentifier</encryptionKeyIdentifier>
        <encryptionUser>frances</encryptionUser>
        <signatureParts>{Element}{http://schemas.xmlsoap.org/soap/env
elope/}Body</signatureParts>
       
 <optimizeParts>//xenc:EncryptedData/xenc:CipherData/xenc:Ciph
erValue</optimizeParts>
      </action>
    </parameter>

    <!-- ================================================= -->
    <!-- Parameters -->
    <!-- ================================================= -->
    <parameter name="hotdeployment"
 locked="false">true</parameter>
...

Observe que Frances está especificando um usuário diferente para criptografia do que o usado para a assinatura digital. Isso não é uma exigência, mas é possível. Observe também a inclusão do elemento optimizeParts , que especifica como Axis2 deve representar os dados criptografados na mensagem.

Vamos ver como tudo isso fica.

A solicitação

Com tudo feito, a mensagem está se tornando um tanto quanto complexa, como é possível ver na Listagem 29.

Listagem 29. A solicitação assinada, selada e criptografada
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv=
            "http://schemas.xmlsoap.org/soap/envelope/"
         xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
   <soapenv:Header>
      <wsse:Security xmlns:wsse="..." soapenv:mustUnderstand="1">
         <xenc:EncryptedKey Id="EncKeyId-229902">
            <xenc:EncryptionMethod Algorithm=
                 "http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
            <ds:KeyInfo xmlns:ds="...">
               <wsse:SecurityTokenReference>
                  <wsse:KeyIdentifier EncodingType="http://docs.oasis
-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-
1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/o
asis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier"
>Xeg55vRyK3ZhAEhEf+YT0z986L0=</wsse:KeyIdentifier>
               </wsse:SecurityTokenReference>
            </ds:KeyInfo>
            <xenc:CipherData>
              
 <xenc:CipherValue>PpAOXj5P0W8ukm...</xenc:CipherValue>
            </xenc:CipherData>
            <xenc:ReferenceList>
               <xenc:DataReference URI="#EncDataId-30957433" />
            </xenc:ReferenceList>
         </xenc:EncryptedKey>
         <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" 
                       Id="Signature-17764792">
            <ds:SignedInfo>
               <ds:CanonicalizationMethod Algorithm=
                      "http://www.w3.org/2001/10/xml-exc-c14n#" />
               <ds:SignatureMethod Algorithm=
                   "http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
               <ds:Reference URI="#id-30957433">
                  <ds:Transforms>
                     <ds:Transform Algorithm=
                      "http://www.w3.org/2001/10/xml-exc-c14n#" />
                  </ds:Transforms>
                  <ds:DigestMethod Algorithm=
                       "http://www.w3.org/2000/09/xmldsig#sha1" />
                 
 <ds:DigestValue>+ECkM6R4GQ7AQ=...</ds:DigestValue>
               </ds:Reference>
            </ds:SignedInfo>
            <SignatureValue>DIeP5AxVmfw...</ds:SignatureValue>
            <ds:KeyInfo Id="KeyId-16675983">
               <wsse:SecurityTokenReference
 xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-
wss-wssecurity-utility-1.0.xsd" wsu:Id="STRId-21866740">
                  <wsse:KeyIdentifier
 EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-
wss-soap-message-security-1.0#Base64Binary"
 ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-
wss-x509-token-profile-1.0#X509SubjectKeyIdentifier">
CuJdE1B2dUFd1dkLZSzQ5vj6MYg=</wsse:KeyIdentifier>
               </wsse:SecurityTokenReference>
            </ds:KeyInfo>
         </ds:Signature>
         <wsu:Timestamp
 xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-
wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-13665843">
            <wsu:Created>2006-06-20T00:46:58.263Z</wsu:Created>
            <wsu:Expires>2006-06-20T00:51:58.263Z</wsu:Expires>
         </wsu:Timestamp>
      </wsse:Security>
   </soapenv:Header>
   <soapenv:Body xmlns:wsu="..." wsu:Id="id-30957433">
      <xenc:EncryptedData Id="EncDataId-30957433" Type=
                "http://www.w3.org/2001/04/xmlenc#Content">
         <xenc:EncryptionMethod Algorithm=
           "http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
         <xenc:CipherData>
            <xenc:CipherValue>DZ3vWPtabb5vBpZMlEYLPjFc8r2DMJ...
fSjXpBFa7gybNA==</xenc:CipherValue>
         </xenc:CipherData>
      </xenc:EncryptedData>
   </soapenv:Body>
</soapenv:Envelope>

Começando pela parte inferior, observe que a solicitação em si está ausente, ou melhor, o Axis2 a substituiu por um elemento EncryptedData que inclui informações sobre como os dados são criptografados, assim como o elemento de dados criptografados em si (em CypherData e CypherValue).

Os dados foram criptografados com uma chave compartilhada, o que significa que a mensagem precisa incluir essa chave para que possa ser decriptografada. A chave compartilhada foi criptografada com a chave pública do destinatário e embarcada no Cabeçalho, no elemento EncryptedKey . Essa chave também inclui ReferenceList, que inclui DataReference que aponta de volta aos dados que essa chave foi usada para criptografar.

Portanto, para reverter a direção, o destinatário (neste caso, o servidor) recebe a mensagem, usa sua própria chave privada para decriptografar a chave compartilhada e, em seguida, usa a chave compartilhada para decriptografar o corpo da mensagem.

Após tudo isso, como fica a resposta?

A resposta

A resposta é bem simples, na verdade, pois Frances não configurou nenhuma OutFlowSecurity no servidor, como é possível ver na Listagem 30.

Listagem 30. A resposta
<?xml version='1.0' encoding='UTF-8'?>
   <soapenv:Envelope xmlns:soapenv=
            "http://schemas.xmlsoap.org/soap/envelope/">
      <soapenv:Header />
      <soapenv:Body>
         <resp:numberOfArcticles xmlns:resp=
                "http://daily-moon.com/cms/" xmlns:tns=
                "http://ws.apache.org/axis2"
         >42</resp:numberOfArcticles>
      </soapenv:Body>
   </soapenv:Envelope>

Essa é uma resposta SOAP perfeitamente válida, exceto por uma coisa. Você pode se lembrar que Frances configurou o cliente para esperar, no mínimo, um registro de data e hora em sua própria InFlowSecurity. Portanto, após tudo isso, a solicitação ainda falhará, a menos que ambos o servidor e o cliente estejam produzindo e esperando os mesmos métodos de segurança.


Reunindo tudo

Neste ponto, Frances e Gene têm alguns exemplos desencontrados, então, eles decidem juntar tudo em uma única implementação para mostrar a Rudy.

A especificação de serviço final

Rudy quer que o serviço aceite somente solicitações de indivíduos (ou entidades) autorizados e n!ao quer que as respostas possam ser lidas pela concorrência. Para fazer isso, Gene e Frances configuram as coisas da seguinte forma:

  1. O cliente incluirá o registro de data e hora, que ele precisará assinar com a chave privada de um usuário aprovado. Isso cuida do problema de acesso autorizado e evita que mensagens sejam interceptadas e reproduzidas.
  2. O servidor incluirá um registro de data e hora, mas também criptografará o corpo da resposta para que se houver alguém na escuta não possa ver os dados que são retornados.

vamos ver como tudo se junta.

O serviço

Do lado do serviço, Gene configura o arquivo services.xml conforme visto na Listagem 31.

Listagem 31. O arquivo services.xml final
<service name="CMSService">

    <description>
        This is a sample web service for the newspaper's 
        Content Managment System.
    </description>

    <parameter name="ServiceClass" 
               locked="false">CMSService</parameter>

    <parameter name="InflowSecurity">
       <action>
            <items>Timestamp Signature</items>
           
 <passwordCallbackClass>PWCallback</passwordCallbackClass>
           
 <signaturePropFile>security.properties</signaturePropFile>
       </action>
    </parameter>

    <parameter name="OutflowSecurity">
      <action>
        <items>Timestamp Signature Encrypt</items>
        <user>gene</user>
        <passwordCallbackClass>PWCallback</passwordCallbackClass>
       
 <signaturePropFile>security.properties</signaturePropFile>
        <signatureKeyIdentifier
                        >SKIKeyIdentifier</signatureKeyIdentifier>
        <encryptionKeyIdentifier
                       >SKIKeyIdentifier</encryptionKeyIdentifier>
        <encryptionUser>frances</encryptionUser>
        <signatureParts>
           {Element}{http://schemas.xmlsoap.org/soap/envelope/}Body
        </signatureParts>
        <optimizeParts>
            //xenc:EncryptedData/xenc:CipherValue/xenc:CipherData
        </optimizeParts> 
       </action>
    </parameter>

    <operation name="getNumberOfArticles">
        <messageReceiver class=
           "org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
    </operation>

</service>

InflowSecurity é o que o servidor espera -- uma mensagem que teve um registro de data e hora incluído e, em seguida, foi assinada -- e OutflowSecurity é o que enviará de volta ao cliente -- uma mensagem que tenha registro de data e hora e tenha sido assinada, com os dados criptografados.

O cliente

Do lado do cliente, Frances configura o reverso, como é possível ver na Listagem 32.

Listagem 32. O arquivo axis2.xml final
<axisconfig name="AxisJava2.0">

    <!-- Engage the security module -->
    <module ref="rampart"/>
    
    <parameter name="OutflowSecurity">
      <action>
        <items>Timestamp Signature</items>
        <user>gene</user>
        <passwordCallbackClass>PWCallback</
passwordCallbackClass>
       
 <signaturePropFile>security.properties</signaturePropFile>
        <signatureKeyIdentifier
                        >SKIKeyIdentifier</signatureKeyIdentifier>
        <signatureParts>
            {Element}{http://docs.oasis-open.org/wss/2004/01/oasis
-200401-wss-wssecurity-utility-1.0.xsd}Timestamp</signatureParts>
      </action>
    </parameter>

    <parameter name="InflowSecurity">
      <action>
        <items>Timestamp Signature Encrypt</items>
        <user>gene</user>
        <passwordCallbackClass>PWCallback</passwordCallbackClass>
       
 <signaturePropFile>security.properties</signaturePropFile>
        <signatureKeyIdentifier
                        >SKIKeyIdentifier</signatureKeyIdentifier>
        <encryptionKeyIdentifier
                       >SKIKeyIdentifier</encryptionKeyIdentifier>
        <encryptionUser>frances</encryptionUser>
        <signatureParts>
           {Element}{http://schemas.xmlsoap.org/soap/envelope/}Body
        </signatureParts>
        <optimizeParts>
           //xenc:EncryptedData/xenc:CipherValue/xenc:CipherData
        </optimizeParts> 
      </action>
    </parameter>

    <!-- ================================================= -->
    <!-- Parameters -->
    <!-- ================================================= -->
    <parameter name="hotdeployment" locked="false">true</parameter>
...

Agora o cliente enviará mensagens com registro de data e hora e assinadas e insiste que quaisquer respostas tenham registro de data e hora, estejam assinadas e criptografadas.

Vamos ver o que isso significa para as mensagens em si.

A solicitação

A Listagem 33 mostra a solicitação final.

Listagem 33. A solicitação final
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv=
          "http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header>
      <wsse:Security xmlns:wsse="http://docs.oasis-
open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
soapenv:mustUnderstand="1">
         <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" 
                                             Id="Signature-5525185">
            <ds:SignedInfo>
               <ds:CanonicalizationMethod Algorithm=
                        "http://www.w3.org/2001/10/xml-exc-c14n#" />
               <ds:SignatureMethod Algorithm=
                     "http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
               <ds:Reference URI="#Timestamp-1741620">
                  <ds:Transforms>
                     <ds:Transform Algorithm=
                        "http://www.w3.org/2001/10/xml-exc-c14n#" />
                  </ds:Transforms>
                  <ds:DigestMethod Algorithm=
                         "http://www.w3.org/2000/09/xmldsig#sha1" />
                  <ds:DigestValue>
                     TQSR9wUuJ7rJi582TsbNjiAUqZI=
                  </ds:DigestValue>
               </ds:Reference>
            </ds:SignedInfo>
             <ds:SignatureValue>aRI5mvvvXZusAB/5cKCx/fOcW+CDjdk1F3Icl
lObVcEOWws9/mV4X2kWEX3hhwK7koX5jMPpl7AtLSbEh8UQGCa8yBua++yveprFl020To
VtePVOcWsBLM+9VHu9bJbhvaaps43RiUkym6xvVU/yL3eKTbhdhB/RQDI3kylXdas=
</ds:SignatureValue>
             <ds:KeyInfo Id="KeyId-26644003">
                <wsse:SecurityTokenReference xmlns:wsu=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-
utility-1.0.xsd" wsu:Id="STRId-26174005">
                   <wsse:KeyIdentifier EncodingType="http://docs.oasi
s-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Bas
e64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-
200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier"
>CuJdE1B2dUFd1dkLZSzQ5vj6MYg=</wsse:KeyIdentifier>
                </wsse:SecurityTokenReference>
             </ds:KeyInfo>
          </ds:Signature>
          <wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/20
04/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
                                          wsu:Id="Timestamp-1741620">
             <wsu:Created>2006-06-22T11:34:02.453Z</wsu:Created>
             <wsu:Expires>2006-06-22T11:39:02.453Z</wsu:Expires>
          </wsu:Timestamp>
       </wsse:Security>
    </soapenv:Header>
    <soapenv:Body>
       <cms:getNumberOfArticles 
                     xmlns:cms="http://daily-moon.com/cms">
          <cms:category>classifieds</cms:category>
       </cms:getNumberOfArticles>
    </soapenv:Body>
 </soapenv:Envelope>

A resposta

A Listagem 34 mostra a resposta final.

Listagem 34. A resposta final
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv=
            "http://schemas.xmlsoap.org/soap/envelope/" 
            xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
   <soapenv:Header>
      <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004
/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
soapenv:mustUnderstand="1">
         <xenc:EncryptedKey Id="EncKeyId-28585008">
            <xenc:EncryptionMethod Algorithm=
                "http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
            <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <wsse:SecurityTokenReference>
               <wsse:KeyIdentifier EncodingType="http://docs.oasis-
open.org/wss/2004/01/oasis-200401-wss-soap-message-security-
1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2
004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKey
Identifier">Xeg55vRyK3ZhAEhEf+YT0z986L0=</wsse:KeyIdentifier>
            </wsse:SecurityTokenReference>
         </ds:KeyInfo>
         <xenc:CipherData>
            <xenc:CipherValue>NSkylkASezzHSp37izSN3xnxf6v/zwN3C70uU2n
UTNk4a9xYxhNcgiVQuS2/Tm3/x3Jm1d9rj2V8x1uqlKmi89MFifN34SDxaDTMBFzhfRv4
CmQSITEFjY1ySVDvMb7WZszGDhVIGYkjcDkoK+SfWdxyuaUdNUbPgEihSnFVRXs=</xen
c:CipherValue>
         </xenc:CipherData>
         <xenc:ReferenceList>
            <xenc:DataReference URI="#EncDataId-19400027" />
         </xenc:ReferenceList>
      </xenc:EncryptedKey>
      <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" 
                                      Id="Signature-17174249">
         <ds:SignedInfo>
            <ds:CanonicalizationMethod Algorithm=
                     "http://www.w3.org/2001/10/xml-exc-c14n#" />
            <ds:SignatureMethod Algorithm=
                  "http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
               <ds:Reference URI="#id-19400027">
                  <ds:Transforms>
                     <ds:Transform Algorithm=
                    "http://www.w3.org/2001/10/xml-exc-c14n#" />
                  </ds:Transforms>
                  <ds:DigestMethod Algorithm=
                       "http://www.w3.org/2000/09/xmldsig#sha1" />
                 
 <ds:DigestValue>HfdufYEGpvPpfz2+HWKui4npV9s=</ds:Di
gestValue>
               </ds:Reference>
               <ds:Reference URI="#SigConf-17122634">
                  <ds:Transforms>
                     <ds:Transform Algorithm=
                        "http://www.w3.org/2001/10/xml-exc-c14n#" />
                  </ds:Transforms>
                  <ds:DigestMethod Algorithm=
                         "http://www.w3.org/2000/09/xmldsig#sha1" />
                 
 <ds:DigestValue>e88WWqudpvW69wN23fgZjQ9ZAio=</ds:Di
gestValue>
               </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue>aZLon//vwkw2G2Jxcligxod/CgxMjwtlefZiho
yUz5FpgSY6RUoI5vuHX2unrWV+EVA2vWdtz/Iyq+RS7j4QtE2XTYovxdyiZPbKXNdFKHy
AkpDr0aDLG9rSjyFVcTrUKgAY06t10zi13Daq95nDMH+wAJCYUO0Vor/u0V9Iv7I=</ds
:SignatureValue>
            <ds:KeyInfo Id="KeyId-22768665">
               <wsse:SecurityTokenReference xmlns:wsu="http://docs.oa
sis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
wsu:Id="STRId-18220809">
                  <wsse:KeyIdentifier EncodingType="http://docs.oasis-
open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Bas
e64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-
200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier"
>CuJdE1B2dUFd1dkLZSzQ5vj6MYg=</wsse:KeyIdentifier>
               </wsse:SecurityTokenReference>
            </ds:KeyInfo>
         </ds:Signature>
         <wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/20
04/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
wsu:Id="Timestamp-6400133">
            <wsu:Created>2006-06-22T11:34:04.062Z</wsu:Created>
            <wsu:Expires>2006-06-22T11:39:04.062Z</wsu:Expires>
         </wsu:Timestamp>
         <wsse11:SignatureConfirmation xmlns:wsse11="http://docs.oasi
s-open.org/wss/2005/xx/oasis-2005xx-wss-wssecurity-secext-1.1.xsd" 
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-
wssecurity-utility-1.0.xsd" Value="aRI5mvvvXZusAB/5cKCx/fOcW+CDjdk1F3
IcllObVcEOWws9/mV4X2kWEX3hhwK7koX5jMPpl7AtLSbEh8UQGCa8yBua++yveprFl02
0ToVtePVOcWsBLM+9VHu9bJbhvaaps43RiUkym6xvVU/yL3eKTbhdhB/RQDI3kylXda
s=" wsu:Id="SigConf-17122634" />
      </wsse:Security>
   </soapenv:Header>
   <soapenv:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/o
asis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-19400027">
      <xenc:EncryptedData Id="EncDataId-19400027" Type=
"http://www.w3.org/2001/04/xmlenc#Content">
         <xenc:EncryptionMethod Algorithm=
              "http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
         <xenc:CipherData>
               <xenc:CipherValue>f6uWHGsYmGwHuno2j4H7a4qCMhPLTlCIg40p
KLciESBzeCT8rvyl+qHXsFkZJq2m4uj9TEFtRX6efQ5MHBEJozMgI03LSVanh6MmHgt5o
ilIJClWcQifEx0Azeo3KWnQKSc9lg0ywhKJH+JVBsPSP7E19jZAsR77wUEBBIprxs5W59
7C/mJh38iXSncwWccE7OCckf1x34FCfKHSqn46MCohZWiPZRjSmAI5dGFMKwttzpmsmXr
LHLVrsjm4w9onis+Xr5gbi3Gcx6P0F2ZJGLBb9bkGh/IvjYutgzRD7zhyRZxUmM/oZTVs
JJ7dA9YOED5l1C64f4yuqR6TtuVw3gIiuspxWafKwlJuuD0/9m6Ri4AvQuOVEioz45MM
5FBCQU+0LFceSlEFFKhN9yLUI9hgLsCYRzc8eedPAhZDjJEDHec5M9LZ0C07sKu7Cvnr
jiino53xZmk5uQHs4JlNoA==</xenc:CipherValue>
         </xenc:CipherData>
      </xenc:EncryptedData>
   </soapenv:Body>
</soapenv:Envelope>

Resumo

Para que os serviços da Web sejam verdadeiramente úteis no ambiente corporativo, precisam ter os recursos de segurança apropriados. Combinando com tecnologias como Assinatura XML e Criptografia XML e fornecendo uma maneira padrão de apresentar essas informações, WS-Security possibilita proteger mensagens SOAP recebidas e de saída contra diversas ameaças de segurança diferentes.

Requerendo assinaturas digitais, é possível limitar acesso a indivíduos ou organizações autorizados, assim como assegurar que as informações não foram alteradas em trânsito. Incluindo criptografia, é possível evitar que dados sejam vistos (ou pelo menos entendidos) por destinatários indesejados. E incluindo registro de data e hora (e assinando-o), é possível evitar que mensagens sejam capturadas e reproduzidas.

Neste tutorial, a equipe do The Daily Moon protegeu os serviços da Web criados em partes anteriores desta série. Em seguida, na Parte 5, eles verão como aplicar políticas de segurança ao serviço.


Download

DescriçãoNomeTamanho
Source codesecurity-code-files.zip20KB

Recursos

Aprender

Obter produtos e tecnologias

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java
ArticleID=757426
ArticleTitle=Entendendo Especificações de Serviços da Web, Parte 4: WS-Security
publish-date=09162011