Serviços da Web Java: Entendendo a WS-Policy

Aprenda os detalhes da WS-Policy e veja quais partes trabalham com três pilhas de serviços da Web Java de software livre

A WS-Policy fornece uma estrutura geral para configurar recursos e opções aplicáveis a um serviço da Web. Você a viu sendo usada em configurações WS-Security nesta série e talvez em outro lugar para outras tecnologias de extensão como o WS-ReliableMessaging. Neste artigo, você aprenderá sobre a estrutura dos documentos da WS-Policy e as formas de conexão de políticas nos serviços na Web Service Description Language (WSDL), com exemplos de configuração de segurança testados no Apache Axis2, Metro e Apache CXF.

Dennis Sosnoski, Architecture Consultant and Trainer, Sosnoski Software Solutions, Inc.

Author photoDennis Sosnoski é um consultor e instrutor especializado em XML e serviços da Web baseados em Java. Sua experiência em desenvolvimento de software profissional se estende por mais de 30 anos, sendo que nos últimos 10 focou tecnologias XML e Java do lado do servidor. Dennis é o desenvolvedor líder da estrutura de software livre JiBX XML Data Binding e a estrutura de serviços da Web associada JiBX/WS, assim como um committer na estrutura de serviços da Web Apache Axis2. Também foi um dos membros do Grupo de Especialistas para as especificações JAX-WS 2.0 e JAXB 2.0. O material para a série Serviços da Web Java é baseado nas aulas de treinamento de Dennis.



06/Dez/2010

Sobre esta série

Os serviços da Web são uma parte crucial do papel da tecnologia Java™ na computação corporativa. Nesta série de artigos, o consultor em XML e serviços da Web Dennis Sosnoski abrange as principais estruturas e tecnologias que são importantes para os desenvolvedores Java que usam os serviços da Web. Acompanhe a série para manter-se informado sobre os desenvolvimentos mais recentes no campo e sobre como usá-los para auxiliar os seus projetos de programação.

Você viu muitos exemplos da WS-Policy e WS-SecurityPolicy na série Serviços da Web Java, mas até o momento sem nenhuma discussão sobre como a WS-Policy realmente funciona (ou, pelo menos, deveria funcionar). Neste artigo, eu vou primeiro preencher as lacunas abordando um pouco mais os fundamentos da WS-Policy. Em seguida veremos como anexar políticas nos serviços nos documentos WSDL. Por fim, vou testar alguns exemplos de configuração da WS-Policy do Axis2, Metro e CXF e contar como eles trabalham na prática. (Consulte a seção Download para obter o código de amostra completo.)

Fundamentos da WS-Policy

A WS-Policy define uma estrutura XML simples que consiste em quatro elementos diferentes e um par de atributos. Esses elementos e atributos, conforme a interpretação da WS-Policy, fornecem uma forma de organizar e combinar asserções de políticas com qualquer nível de complexidade. Para definir as asserções atuais que compõe uma política, use extensões específicas do domínio como a WS-SecurityPolicy, ao invés da WS-Policy per se.

Versões da WS-Policy

Os detalhes da WS-Policy neste artigo são específicos para a WS-Policy 1.5 "oficial" publicada pela W3C, mas as mesmas regras gerais se aplicam para a versão "submission" anterior que ainda é amplamente utilizada. Como ocorre com outras tecnologias WS-*, é possível identificar a versão usada por um documento verificando o namespace XML. O namespace da WS-Policy 1.5 é http://www.w3.org/ns/ws-policy e o da versão submission é http://schemas.xmlsoap.org/ws/2004/09/policy. Neste artigo, eu uso o namespace http://www.w3.org/ns/ws-policy, representado pelo prefixo wsp

Para conveniência, a WS-Policy define uma expressão de política na forma normal e um conjunto de regras que podem ser usadas para criar expressões de políticas mais compactas. A forma normal pode ser detalhada de alguma forma, então (apesar das recomendações da WS-Policy determinando que "a forma normal de uma expressão de política DEVERÁ ser utilizada quando possível") a maioria dos autores de documentos sobre políticas tende a usar ao menos algumas seções das regras de expressão compactas para facilitar o uso dos documentos para as pessoas. A interpretação dos documentos sobre políticas é baseada na forma normal, então esse será o primeiro item abordado.

Expressão na Forma Normal

A expressão de política na forma normal usa no mínimo três elementos, que devem ser aninhados sempre em uma ordem específica. O elemento mais externo é sempre o <wsp:Policy> e ele deve conter um único elemento filho <wsp:ExactlyOne> . O <wsp:ExactlyOne> aninhado, por sua vez, contém qualquer número (possivelmente zero) de elementos filhos <wsp:All> . Então a expressão de política na forma normal mais simples é <wsp:Policy><wsp:ExactlyOne/></wsp:Policy>.

Todas as asserções de políticas na forma normal devem ser aninhadas com um elemento <wsp:All> . Essas asserções de políticas podem conter asserções de políticas. Isso foi visto nos artigos anteriores dessa série, nos quais diversas asserções da WS-SecurityPolicy continham expressões de políticas aninhadas. Em uma expressão de política na forma normal, todas essas asserções de políticas aninhadas também devem estar na forma normal. (Na verdade, elas devem estar em um subconjunto ainda mais restritivo da forma normal, onde cada elemento <wsp:ExactlyOne> com exceção do primeiro possui somente um elemento filho <wsp:All> .) A Listagem 1 mostra um extrato com diversos exemplos de expressões de políticas aninhadas, expressas na forma normal:

Listagem 1. Extrato de WS-SecurityPolicy com expressões de políticas aninhadas
                <wsp:Policy> <wsp:ExactlyOne>
                <wsp:All> <sp:AsymmetricBinding
                xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
                <wsp:Policy> <wsp:ExactlyOne>
                <wsp:All> <sp:InitiatorToken>
                <wsp:Policy> <wsp:ExactlyOne>
                <wsp:All> <sp:X509Token
                sp:IncludeToken=".../IncludeToken/AlwaysToRecipient">
                <wsp:Policy> <wsp:ExactlyOne>
                <wsp:All>
                <sp:RequireThumbprintReference/>
                </wsp:All> </wsp:ExactlyOne>
                </wsp:Policy> </sp:X509Token>
                </wsp:All> </wsp:ExactlyOne>
                </wsp:Policy> </sp:InitiatorToken>
                ...

Apesar das diversas camadas de elementos aninhados, a semântica dessa estrutura é simples. Na expressão de política na forma normal, <wsp:Policy> é somente um wrapper para a expressão de política e, no caso de expressões de políticas de nível superior, um local para anexar um nome ou um identificador na política. O elemento <wsp:ExactlyOne> aninhado representa uma combinação ou das alternativas representadas pelos elementos <wsp:All> aninhados (então a expressão de política completa será verdadeira se qualquer uma das alternativas aninhadas for verdadeira). Cada elemento <wsp:All> representa uma combinação e das asserções de políticas aninhadas (então a alternativa será verdadeira somente se todas as asserções forem verdadeiras).

Política Não Normalizada

As expressões de políticas não precisam estar na forma normal. As expressões de políticas não normais podem incluir alternativas aninhadas (diversos elementos filho <wsp:All> de um elemento <wsp:ExactlyOne> abaixo do nível superior) e também podem usar as opções de expressões de políticas compactas que serão discutidas na próxima seção.

Se você estudou a teoria da lógica, talvez reconheça a representação da forma normal (sem alternativas aninhadas) como equivalente à forma normal disjuntiva de uma expressão lógica. As expressões de políticas são, na verdade, somente expressões lógicas que usam o formato dos sinais de maior e menor, com asserções como cláusulas. A teoria da lógica mostra que qualquer expressão lógica pode ser convertida para a forma normal disjuntiva e o mesmo princípio se aplica às expressões de políticas escritas com alternativas aninhadas — elas podem ser expandidas para uma forma normal de representação com alternativas somente no nível superior. A principal vantagem da expressão de política na forma normal é facilitar a verificação da compatibilidade de duas políticas através do programa — se as duas políticas na forma normal forem compatíveis, elas terão um ou mais elementos <wsp:All> de nível superior contendo os mesmos conjuntos de asserções.

Expressão de Política Compacta

A expressão de política na forma normal pode ser extensa, principalmente se incluir alternativas aninhadas. A WS-Policy define opções que podem ser usadas para criar expressões de políticas mais concisas do que o permitido na forma normal, facilitando o entendimento das políticas. A documentação da WS-Policy é confusa ao se referir algumas vezes às políticas usando essas opções como sendo na forma compacta. Na verdade, muitas expressões de políticas compactas podem ser equivalentes a uma única expressão na forma normal. Neste artigo, usarei somente expressões compactas para me referir ás políticas usando uma ou mais dessas opções.

Um dos recursos das opções de expressões compactas é a possibilidade de expressar políticas através do aninhamento dos elementos básicos da política (chamados operadores nos termos da política, pois cada elemento implica em uma interpretação particular das asserções aninhadas) em qualquer ordem. As regras de aninhamento também definem uma interpretação do elemento <wsp:Policy> usado diretamente (sem o elemento filho <wsp:ExactlyOne> único necessário na forma normal) como equivalente ao elemento <wsp:All>, provavelmente o recurso de expressão compacto mais amplamente utilizado.

A Listagem 2 mostra uma expressão compacta da mesma política mostrada na Listagem 1, usando a representação <wsp:Policy> . Essa versão tem menos da metade do comprimento da primeira versão e a maioria das pessoas a considera mais fácil de ser entendida.

Listagem 2. Política simples na forma compacta
 <wsp:Policy>
                <sp:AsymmetricBinding
                xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
                <wsp:Policy> <sp:InitiatorToken>
                <wsp:Policy> <sp:X509Token
                sp:IncludeToken=".../IncludeToken/AlwaysToRecipient">
                <wsp:Policy>
                <sp:RequireThumbprintReference/>
                </wsp:Policy> </sp:X509Token>
                </wsp:Policy> </sp:InitiatorToken>
                ...

A WS-Policy define um conjunto de transformações que pode ser aplicado para converter expressões de políticas usando as opções compactas na forma normal, então não há razão para usar a forma normal diretamente. É muito mais fácil para os computadores transformarem expressões compactas na forma normal do que humanos interpretarem a forma normal.

Inclusão de Política

Além de simplificar o aninhamento de elementos, a expressão compacta também fornece uma forma de referenciar e reutilizar expressões de políticas. Faça isso com o quarto elemento da WS-Policy, <wsp:PolicyReference>. Um elemento <wsp:PolicyReference> pode aparecer nos mesmos locais da asserção de política. A expressão de política referenciada é efetivamente substituída pela referência da política (tecnicamente com um elemento <wsp:All> substituindo o elemento <wsp:Policy> ). Essa abordagem de substituição é chamada de inclusão de política.

A Listagem 3 ilustra o uso de inclusão de política, mostrando a expressão de política da Listagem 2 refatorada para uma forma usando uma expressão de política separada e uma referência:

Listagem 3. Referência da política
                <!-- Client X.509 token policy assertion. -->
                <wsp:Policy wsu:Id="ClientX509"
                xmlns:wsu="http://.../oasis-200401-wss-wssecurity-utility-1.0.xsd">
                <sp:InitiatorToken> <wsp:Policy>
                <sp:X509Token
                sp:IncludeToken=".../IncludeToken/AlwaysToRecipient">
                <wsp:Policy>
                <sp:RequireThumbprintReference/>
                </wsp:Policy> </sp:X509Token>
                </wsp:Policy> </sp:InitiatorToken>
                </wsp:Policy> <wsp:Policy>
                <sp:AsymmetricBinding
                xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
                <wsp:Policy> <wsp:PolicyReference
                URI="#ClientX509"/> ...

As referências às políticas podem ser usadas para expressões de políticas locais, conforme mostrado na Listagem 3, e para expressões de políticas externas. Para expressões de políticas externas, o atributo do URI de referência normalmente fornece a URL real da política externa.

Conforme será visto nos exemplos de teste de política fornecidos ainda neste artigo, a inclusão de política não é universalmente suportada no momento. Isso limita a função desse recurso interessante.

Alternativas da Política

Conforme visto anteriormente, a estrutura da WS-Policy suporta opções de alternativas como parte da política, através do elemento <wsp:ExactlyOne> . Com a expressão compacta, também é possível (pelo menos na teoria) usar atributos especiais para criar opções. De acordo com a recomendação da WS-Policy, é possível adicionar o atributo wsp:Optional="true" a qualquer asserção de política para tornar a asserção uma opção ao invés de um requisito, mesmo quando a asserção for um filho de um elemento <wsp:All> ou <wsp:Policy> .

As alternativas da política parecem ser um recurso útil, mas é difícil sugerir um exemplo concreto não trivial. Na prática, geralmente esses recursos são usados para tornar um componente particular do processo de segurança, como o UsernameToken, opcional. As alternativas mais complexas, como permitir ao cliente fornecer identificação na forma de um UsernameToken ou de um certificado X.509, parecem estar além dos recursos das implementações atuais do WS-SecurityPolicy.


Conexão de Política

No WSDL 1.1 (um pouco ultrapassado, mas ainda a forma de definição de serviço mais amplamente utilizada), as definições de serviço usam uma estrutura hierárquica. A primeira camada (na parte inferior) consiste nos elementos <wsdl:message> que definem a estrutura XML das mensagens enviadas e recebidas do serviço. A segunda camada consiste nos elementos <wsdl:portType> que definem os conjuntos de operações, com cada operação especificada pelas mensagens de entrada, saída ou de falha. A terceira camada consiste nos elementos <wsdl:binding> que associam um protocolo de mensagem particular (como o SOAP) e um método de acesso a um elemento <wsdl:portType>. A quarta camada são as definições do terminal em serviço na forma de elementos <wsdl:port> que especificam o endereço no qual um elemento <wsdl:binding> pode ser acessado.

Esquema(s) WSDL

O WSDL 1.1 tem um longo e variado histórico no que se refere a definições de esquema XML. A aceitação do WSDL 1.1 original incluía uma descrição em texto de como os documentos XML WSDL deveriam ser estruturados e uma definição do esquema XML. Infelizmente, o esquema XML fornecido não correspondia ao texto. Isso foi corrigido em uma versão modificada do esquema posteriormente, mas o documento do WSDL 1.1 não foi atualizado para refletir a alteração. Em seguida, o grupo WS-I Basic Profile decidiu fazer outras alterações no esquema XML, então foi criado o que parece ser a versão das melhores práticas desse esquema indefinido. Geralmente, os documentos escritos em uma versão não são compatíveis com outras versões (apesar do uso do mesmo namespace), mas felizmente a maioria das ferramentas de serviços da Web ignora o esquema e aceita tudo o que parece razoável. Consulte a seção Recursos para obter links para os diversos esquemas do WSDL.

A WS-Policy permite a conexão de políticas às definições de serviço WSDL em diversos pontos diferentes que não correspondem exatamente às camadas da definição. Considerando que as camadas representam uma estrutura lógica das definições de serviço, a WS-Policy está mais preocupada com mensagens e grupos de mensagens. Os quatro níveis de agrupamentos de mensagens usados pela WS-Policy são:

  • Mensagem: A política é aplicada a uma mensagem particular (sempre que a mensagem for usada se a política for anexada através do elemento <wsdl:message> ou quando usada por uma operação particular se for anexada através das definições de entrada/saída/falha da operação no elemento <wsdl:portType> ou no elemento <wsdl:binding> ).
  • Operação: A política é aplicada a todas as trocas de mensagens de uma operação particular (política anexada através do elemento <wsdl:operation> com <wsdl:binding> ou <wsdl:portType>).
  • Terminal: A política é aplicada a todas as trocas de mensagens de uma ligação de serviço particular (política anexada através de <wsdl:port> ou <wsdl:binding>) ou para todas as ligações de serviço baseadas em um tipo de porta particular (política anexada ao <wsdl:portType>).
  • Serviço: a política é aplicada a todos os terminais e operações associados a um serviço (política anexada no elemento <wsdl:service> ).

O principal mecanismo de conexão de políticas usado pelo WSDL é o mesmo usado para referenciar uma política em outra política — o elemento <wsp:PolicyReference> discutido na seção Inclusão de Política . Esse elemento da WS-Policy pode ser adicionado como um filho em qualquer elemento WSDL listado anteriormente para especificar a política a ser aplicada no nível de agrupamentos de mensagens. Também é possível incorporar uma política diretamente como um elemento <wsp:Policy> com qualquer conteúdo apropriado, mas normalmente é melhor usar referências para a estrutura do WSDL permanecer ordenada.

As políticas aplicadas em um nível dos agrupamentos de mensagens são herdadas pelas camadas inferiores, combinadas com um elemento <wsp:All> . Isso torna a política real (ou efetiva, nos termos da WS-Policy) aplicada a cada mensagem a conjunção de todas as políticas aplicadas nas camadas da mensagem, operação, terminal e serviço. Então a política não é determinada somente pela mensagem, mas também pelo contexto no qual a mensagem é usada

A Listagem 4 ilustra essa operação, mostrando o esqueleto da definição do WSDL com referências às políticas:

Listagem 4. Exemplo de conexão de política
 <wsdl:binding
                name="LibrarySoapBinding" type="wns:Library">
                <wsp:PolicyReference
                xmlns:wsp="http://www.w3.org/ns/ws-policy"
                URI="#UsernameToken"/> <wsdlsoap:binding
                style="document"
                transport="http://schemas.xmlsoap.org/soap/http"/>
                <wsdl:operation name="addBook">
                <wsp:PolicyReference
                xmlns:wsp="http://www.w3.org/ns/ws-policy"
                URI="#AsymmEncr"/> ... </wsdl:operation>
                </wsdl:binding>

Nesse caso, uma política que requer um UsernameToken foi anexada no nível <wsdl:binding> , e uma política adicional que requer criptografia de mensagem assimétrica foi anexada à operação addBook definida como parte dessa ligação. Assumindo que esse exemplo mostra o conjunto completo de referências às políticas do WSDL, o UsernameToken é sempre requerido, mas a autenticação da mensagem é somente usada para a operação addBook .

Como alternativa ao uso do <wsp:PolicyReference> para referenciar políticas diretamente dos elementos do WSDL, é possível usar o atributo wsp:PolicyURIs . É possível adicionar esse atributo a qualquer elemento do WSDL no qual uma política possa ser anexada. Funciona basicamente da mesma forma que usar elementos <wsp:PolicyReference> filhos.

Conexão de WS-SecurityPolicy

A WS-SecurityPolicy especifica os níveis de agrupamento de mensagens nos quais diferentes tipos de asserções de políticas podem ser anexados a uma descrição do serviço. Por exemplo: a asserção <sp:TransportBinding> usada para especificar a segurança do transporte só poderá ser anexada no nível do terminal, enquanto as asserções <sp:AsymmetricBinding> e <sp:SymmetricBinding> usadas para especificar criptografias ou autenticações de mensagens só poderão ser usadas no nível do terminal ou da operação.

Embora o <sp:AsymmetricBinding> ou o <sp:SymmetricBinding> não possa ser especificado no nível da mensagem, é possível especificar os componentes da mensagem a serem criptografados ou autenticados no nível da mensagem. Isso significa que, pelo menos na teoria, é possível especificar criptografia ou autenticação por mensagem.


Exemplos de Políticas

Agora que você aprendeu os princípios da WS-Policy e como ela funciona com o WSDL, é hora de testar alguns exemplos de políticas usando esses princípios. Assim como nos artigos anteriores, eu testei o código deste artigo com todas as três principais pilhas de serviços da Web de software livre Java: Axis2, Metro e CXF.

A Listagem 5 mostra um exemplo (effective1.wsdl no download do código de amostra) usando três níveis de conexão de política em uma definição de serviço WSDL. As três políticas usadas são:

  • UsernameToken: Requer um UsernameToken com uma senha hash.
  • SymmEncr: Requer uma criptografia simétrica usando uma chave genérica gerada pelo cliente.
  • EncrBody: Requer a criptografia do corpo da mensagem.
Listagem 5. Exemplo de política efetiva
 <wsdl:definitions
                targetNamespace="http://ws.sosnoski.com/library/wsdl"...>
                <wsp:Policy wsu:Id="UsernameToken"
                xmlns:wsp="http://www.w3.org/ns/ws-policy"...>
                <sp:SupportingTokens> <wsp:Policy>
                <sp:UsernameToken
                sp:IncludeToken=".../IncludeToken/AlwaysToRecipient">
                <wsp:Policy> <sp:HashPassword/>
                </wsp:Policy> </sp:UsernameToken>
                </wsp:Policy> </sp:SupportingTokens>
                </wsp:Policy> <wsp:Policy wsu:Id="SymmEncr"
                xmlns:wsp="http://www.w3.org/ns/ws-policy"...>
                <sp:SymmetricBinding> <wsp:Policy>
                <sp:ProtectionToken> <wsp:Policy>
                <sp:X509Token
                sp:IncludeToken=".../IncludeToken/Never"> ...
                </sp:X509Token> </wsp:Policy>
                </sp:ProtectionToken> ...
                </wsp:Policy> </sp:SymmetricBinding>
                ... </wsp:Policy> <wsp:Policy
                wsu:Id="EncrBody"
                xmlns:wsp="http://www.w3.org/ns/ws-policy"...>
                <sp:EncryptedParts> <sp:Body/>
                </sp:EncryptedParts> </wsp:Policy>
                ... <wsdl:binding name="LibrarySoapBinding"
                type="wns:Library"> <wsp:PolicyReference
                    xmlns:wsp="http://www.w3.org/ns/ws-policy"
                    URI="#UsernameToken"/> ... <wsdl:operation
                name="getBook"> <wsp:PolicyReference
                    xmlns:wsp="http://www.w3.org/ns/ws-policy"
                    URI="#SymmEncr"/> <wsdlsoap:operation
                soapAction="urn:getBook"/> <wsdl:input
                name="getBookRequest"> <wsdlsoap:body
                use="literal"/> </wsdl:input>
                <wsdl:output name="getBookResponse">
                    <wsp:PolicyReference
                    xmlns:wsp="http://www.w3.org/ns/ws-policy"
                    URI="#EncrBody"/> <wsdlsoap:body
                use="literal"/> </wsdl:output>
                </wsdl:operation> <wsdl:operation
                name="getBooksByType">
                    <wsp:PolicyReference
                    xmlns:wsp="http://www.w3.org/ns/ws-policy"
                    URI="#SymmEncr"/> <wsdlsoap:operation
                soapAction="urn:getBooksByType"/> <wsdl:input
                name="getBooksByTypeRequest"> <wsdlsoap:body
                use="literal"/> </wsdl:input>
                <wsdl:output name="getBooksByTypeResponse">
                    <wsp:PolicyReference
                    xmlns:wsp="http://www.w3.org/ns/ws-policy"
                    URI="#EncrBody"/> <wsdlsoap:body
                use="literal"/> </wsdl:output>
                </wsdl:operation> <wsdl:operation
                name="getTypes"> ... </wsdl:operation>
                <wsdl:operation name="addBook">
                    <wsp:PolicyReference
                    xmlns:wsp="http://www.w3.org/ns/ws-policy"
                    URI="#SymmEncr"/> <wsdlsoap:operation
                soapAction="urn:addBook"/> <wsdl:input
                name="addBookRequest">
                    <wsp:PolicyReference
                    xmlns:wsp="http://www.w3.org/ns/ws-policy"
                    URI="#EncrBody"/> <wsdlsoap:body
                use="literal"/> </wsdl:input>
                <wsdl:output name="addBookResponse">
                <wsdlsoap:body use="literal"/>
                </wsdl:output> <wsdl:fault
                name="addDuplicateFault">
                    <wsp:PolicyReference
                    xmlns:wsp="http://www.w3.org/ns/ws-policy"
                    URI="#EncrBody"/> <wsdlsoap:fault
                name="addDuplicateFault" use="literal"/>
                </wsdl:fault> </wsdl:operation>
                </wsdl:binding> ...
                </wsdl:definitions>

As referências às políticas (mostradas em negrito) no documento WSDL da Listagem 5 anexam a política UsernameToken ao <wsdl:binding>, então o UsernameToken será necessário em todas as operações. A política SymmEncr é anexada ao <wsdl:operation> individual para todas as operações de troca de informações de livro e a política EncrBody é anexada às mensagem que incluem informações de livro — para que as informações de livro sejam sempre enviadas na forma criptografada.

Essa é uma política complicada, pois requer que o cliente gere uma chave secreta e a envie para o servidor com a mensagem de solicitação, apesar de a chave secreta ser somente usada para criptografar a resposta. O Axis2 1.5.2 e o Metro 2.0.1 não são capazes de tratar esse caso de nenhuma forma. O Axis2 ignorou completamente os componentes da política que usam os namespaces de política WS-Policy 1.5. Quando eu alterei o uso para o namespace de envio o Axis2 foi além, gerando uma configuração razoável no código do cliente — mas ignorou a política no cliente e no servidor no tempo de execução, executando sem segurança. O Metro gerou uma mensagem de solicitação com um UsernameToken, mas sem informações da chave secreta.

O CXF 2.3.0 se saiu melhor, manipulando a política corretamente exceto em dois casos. Quando a operação addBook é bem-sucedida, a mensagem de resposta não usa criptografia. O servidor do CXF tratou isso corretamente, mas o cliente emitiu uma exceção ao processar a resposta O outro erro do CXF ocorreu com a operação addBook , mas nesse caso quando a solicitação falha. A resposta de retorno de falha do aplicativo deveria usar criptografia, mas o servidor do CXF enviou a resposta sem criptografia e o cliente a aceitou sem nenhuma queixa.

A política da Listagem 5 demonstra o uso seletivo da criptografia de mensagem, criptografando somente as mensagens que incluem informações de livros. No entanto, essa política usa criptografia simétrica. Seria ótimo poder fazer a mesma coisa usando criptografia assimétrica, na qual o cliente possui o seu próprio certificado (especialmente quando quiser assinar mensagens para verificação do remetente). A Listagem 6 mostra um exemplo projetado para esse propósito (effective2.wsdl no download). Esse exemplo usa somente duas políticas do WSDL:

  • AsymmBinding: Requer uma criptografia assimétrica usando certificados duplos.
  • SignBody: Requer a assinatura do corpo da mensagem.
Listagem 6. Exemplo de assinatura assimétrica
 <wsdl:definitions
                targetNamespace="http://ws.sosnoski.com/library/wsdl"...>
                <wsp:Policy wsu:Id="AsymmBinding"
                xmlns:wsp="http://www.w3.org/ns/ws-policy" ...>
                <sp:AsymmetricBinding> <wsp:Policy>
                <sp:InitiatorToken> <wsp:Policy>
                <sp:X509Token
                sp:IncludeToken=".../IncludeToken/AlwaysToRecipient"> ...
                </sp:X509Token> </wsp:Policy>
                </sp:InitiatorToken>
                <sp:RecipientToken> <wsp:Policy>
                <sp:X509Token
                sp:IncludeToken=".../IncludeToken/Never"> ...
                </sp:X509Token> </wsp:Policy>
                </sp:RecipientToken> ...
                </wsp:Policy>
                </sp:AsymmetricBinding>
                </wsp:Policy> <wsp:Policy wsu:Id="SignBody"
                xmlns:wsp="http://www.w3.org/ns/ws-policy" ...>
                <sp:SignedParts> <sp:Body/>
                </sp:SignedParts> </wsp:Policy> ...
                <wsdl:binding name="LibrarySoapBinding"
                type="wns:Library"> ... <wsdl:operation
                name="getBook"> <wsp:PolicyReference
                    xmlns:wsp="http://www.w3.org/ns/ws-policy"
                    URI="#AsymmBinding"/>
                <wsdlsoap:operation soapAction="urn:getBook"/>
                <wsdl:input name="getBookRequest">
                <wsdlsoap:body use="literal"/>
                </wsdl:input> <wsdl:output
                name="getBookResponse">
                    <wsp:PolicyReference
                    xmlns:wsp="http://www.w3.org/ns/ws-policy"
                    URI="#SignBody"/> <wsdlsoap:body
                use="literal"/> </wsdl:output>
                </wsdl:operation> <wsdl:operation
                name="getBooksByType">
                    <wsp:PolicyReference
                    xmlns:wsp="http://www.w3.org/ns/ws-policy"
                    URI="#AsymmBinding"/>
                <wsdlsoap:operation
                soapAction="urn:getBooksByType"/> <wsdl:input
                name="getBooksByTypeRequest"> <wsdlsoap:body
                use="literal"/> </wsdl:input>
                <wsdl:output name="getBooksByTypeResponse">
                    <wsp:PolicyReference
                    xmlns:wsp="http://www.w3.org/ns/ws-policy"
                    URI="#SignBody"/> <wsdlsoap:body
                use="literal"/> </wsdl:output>
                </wsdl:operation> <wsdl:operation
                name="getTypes"> ... </wsdl:operation>
                <wsdl:operation name="addBook">
                    <wsp:PolicyReference
                    xmlns:wsp="http://www.w3.org/ns/ws-policy"
                    URI="#AsymmBinding"/>
                <wsdlsoap:operation soapAction="urn:addBook"/>
                <wsdl:input name="addBookRequest">
                    <wsp:PolicyReference
                    xmlns:wsp="http://www.w3.org/ns/ws-policy"
                    URI="#SignBody"/> <wsdlsoap:body
                use="literal"/> </wsdl:input>
                <wsdl:output name="addBookResponse">
                <wsdlsoap:body use="literal"/>
                </wsdl:output> <wsdl:fault
                name="addDuplicateFault"> <wsdlsoap:fault
                name="addDuplicateFault" use="literal"/>
                </wsdl:fault> </wsdl:operation>
                </wsdl:binding> ...
                </wsdl:definitions>

O exemplo da Listagem 6 usa criptografia assimétrica para assinar todas as mensagens que fornecem informações de livro. Isso significa que as mensagens de resposta getBook e getBooksByType devem ser assinadas pelo servidor, enquanto a mensagem de solicitação addBook deve ser assinada pelo cliente. Como a criptografia assimétrica está sendo usada, na qual cada lado possui seu próprio certificado e chave privada, esse exemplo deveria ser mais simples de ser tratado do que o exemplo de criptografia simétrica da Listagem 5 .

Referências às Políticas Externas

As referências às políticas externas não se encaixam corretamente na estrutura dos exemplos fornecidos, mas eu as testei. Para o teste, eu usei referências relativas, na forma <wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy" URI="./asymm-binding-policy.xml"/> e URLs absolutas hospedadas em um servidor da Web. O Axis2 e o Metro não foram capazes de resolver referências à políticas desse tipo. Elas funcionaram corretamente no CXF.

O Axis2 falhou da mesma forma que ocorreu exemplo anterior, ignorando completamente os componentes da política que usam os namespaces de política WS-Policy 1.5 e gerando a política do cliente, mas ignorando-a em ambos os lados quanto eu mudei para o namespace de envio. (Para obter um exemplo mais simples das políticas efetivas que funcionam com o Axis2, consulte o artigo "Serviços da Web Java: Uso Granular do WS-Security.")

O Metro não foi capaz de trabalhar com a configuração de política fornecida, emitindo um NullPointerException no cliente com a primeira solicitação. Após alguma investigação, descobri que o problema é resolvido ao anexar uma política no nível do terminal, ao invés de anexá-la somente nos níveis de operação e de mensagem. O exemplo do Metro inclui um effective3.wsdl com a política #AsymmBinding referenciada somente para o <wsdl:binding>, e esse exemplo foi executado sem problemas (apesar de, como ocorreu com o CXF no caso simétrico, o Metro não aplicar a segurança na resposta de falha do aplicativo).

O CXF também falhou com a configuração de política da Listagem 6 , mas sem uma solução alternativa fácil no código atual. O código do cliente CXF gerou de forma incorreta uma assinatura ao enviar a mensagem de solicitação getBook e o código do servidor falhou no processamento da mensagem de solicitação. Então parece que o código CXF atual insiste em gerar uma assinatura quando um AsymmetricBinding é usado, mesmo quando nada está sendo assinado.


Conclusão da Política

A WS-Policy define uma estrutura flexível e poderosa para expressar qualquer forma de restrição. Infelizmente, as implementações dos processamentos da WS-Policy e da WS-SecurityPolicy usados pelas pilhas de serviços da Web não implementam muito essa flexibilidade. Devido a essa falta de suporte na implementação, muitos outros recursos úteis da WS-Policy não podem ser usados para serviços da Web projetados para interoperar com uma ampla gama de pilhas de serviços da Web.

O processamento básico de políticas efetivas, nas quais as políticas são anexadas em diferentes pontos nas definições de serviço do WSDL, é o recurso principal do design da política e do WSDL e deveria ser usado quando apropriado para os seus serviços. Mas um dos possíveis recursos úteis desse tipo de configuração — a possibilidade de assinar e criptografar mensagens seletivamente de forma individual — não funciona com segurança. Devido a essa limitação, provavelmente é melhor permanecer com as conexões de políticas nos níveis <wsdl:binding> e <wsdl:operation> por enquanto para uma melhor interoperabilidade.

As políticas externas podem ser especialmente úteis em ambientes do tipo SOA, nos quais um conjunto de políticas comuns pode ser configurado para uso por toda a organização e cada serviço pode referenciar as políticas apropriadas de acordo com as necessidades. Apesar desse recurso não ser suportado no momento por todas as pilhas de serviços da Web Java de software livre (somente o Apache CXF suporta o recurso corretamente), as grandes organizações podem optar por usar o recurso de qualquer forma e restringir as implementações de serviços da Web usando uma das pilhas (de software livre ou comercial) que ofereça suporte. Também é possível obter o mesmo efeito de outras formas, como através do uso do conteúdo do WSDL.

No próximo artigo da série, eu resumirei os problemas de desempenho e de interoperabilidade com as três principais pilhas de serviços da Web Java e apresentarei uma visão geral da comparação dessas pilhas para uso na implementação de serviços da Web seguros. Se usar serviços da Web seguros na sua organização, não perca o próximo artigo.


Download

DescriçãoNomeTamanho
Sample code for this articlej-jws18.zip94KB

Recursos

Aprender

Discutir

  • Participe da comunidade do My developerWorks. Entre em contato com outros usuários do developerWorks e explore os blogs, fóruns, grupos e wikis voltados para desenvolvedores.

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, WebSphere, Software livre
ArticleID=594724
ArticleTitle=Serviços da Web Java: Entendendo a WS-Policy
publish-date=12062010