Você viu muitos exemplos da WS-Policy e WS-SecurityPolicy na primeira e segunda parte da 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, 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.
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.
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.
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.
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
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
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.
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.
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.
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.
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.
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.
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.
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.
Recursos
Aprender
-
O W3C Web Services
Policy Working Group: Esse grupo define a especificação
da WS-Policy. -
OASIS Web Services Secure Exchange (WS-SX) TC: Essa
organização é responsável pelas especificações da
WS-SecurityPolicy, da WS-SecureConversation e da
WS-Trust. - Esquemas do WSDL 1.1: As
especificações do WSDL
1.1 incluem uma definição de esquema que não corresponde ao texto. Esse
esquema foi substituído posteriormente por esse
esquema, apesar do texto do WSDL 1.1 nunca ter sido
atualizado para refletir a alteração. A organização de
interoperabilidade WS-I definiu uma terceira versão, que provavelmente é a melhor de
todas. - “Understand WS-Policy processing” (Paul Nolan,
developerWorks, dezembro de 2004): Esse artigo aborda os
detalhes da normalização e da comparação da
WS-Policy. - Apache
Axis2/Java: Visite a página inicial do projeto do
mecanismo de serviços da Web Axis2. - Metro: Visite o Web
site do Metro para obter documentações e efetuar downloads. - Apache CXF: Visite o site da pilha de serviços da Web
CXF. - Navegue na livraria de tecnologia para obter livros sobre estes e
outros tópicos técnicos. -
Zona de
tecnologia Java do developerWorks: Encontre centenas de
artigos sobre cada aspecto da programação Java.
***
artigo publicado originalmente no developerWorks Brasil, por Dennis Sosnoski
Dennis 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.