Pergunta

Preciso chamar um serviço web escrito em .NET a partir de Java.O serviço da web implementa a pilha WS-Security (WSE 2 ou WSE 3, não está claro nas informações que tenho).

As informações que recebi do provedor de serviços incluíam WSDL, um arquivo policyCache.config, alguns códigos C# de amostra e um aplicativo de amostra que pode chamar o serviço com êxito.

Isso não é tão útil quanto parece porque não está claro como devo usar essas informações para escrever um cliente Java.Se a solicitação de serviço web não for assinada de acordo com a política, ela será rejeitada pelo serviço.Estou tentando usar o Apache Axis2 e não consigo encontrar nenhuma instrução sobre como devo usar o arquivo policyCahce.config e o WSDL para gerar um cliente.

Existem vários exemplos que encontrei na Web, mas em todos os casos os autores dos exemplos tinham controle tanto do serviço quanto do cliente e, portanto, foram capazes de fazer ajustes em ambos os lados para fazê-lo funcionar.Eu não estou nessa posição.

Alguém fez isso com êxito?

Foi útil?

Solução 2

Esta parece ser uma pergunta popular, então fornecerei uma visão geral do que fizemos em nossa situação.

Parece que os serviços criados no .NET estão seguindo um padrão de endereçamento ws mais antigo (http://schemas.xmlsoap.org/ws/2004/03/addressing/) e axis2 entende apenas o padrão mais recente (http://schemas.xmlsoap.org/ws/2004/08/addressing/).

Além disso, o arquivo policyCache.config fornecido está em um formato que o módulo de muralha axis2 não consegue entender.

Então, resumidamente, as etapas que tivemos que seguir:

  • Leia o policyCache.config e tente entendê-lo.Em seguida, reescreva-o em uma política que a muralha possa entender.(Alguns documentos atualizados ajudou.)
  • Configure a muralha com esta política.
  • Pegue as chaves fornecidas no arquivo .pfx e converta-as em um armazenamento de chaves java.Existe um utilitário que acompanha o Jetty que pode fazer isso.
  • Configure a muralha com esse armazenamento de chaves.
  • Escreva um manipulador axis2 personalizado que converta retroativamente o material de endereçamento ws mais recente que sai do axis2 no material mais antigo esperado pelo serviço.
  • Configure o axis2 para usar o manipulador em mensagens de saída.

No final, foi muita configuração e código para algo que deveria ser um padrão aberto suportado pelos fornecedores.

Embora eu não tenha certeza de qual é a alternativa... você pode esperar que os fornecedores (ou, neste caso, o único fornecedor) tenham certeza de que tudo funcionará em interoperabilidade?

Como pós-escrito, acrescentarei que não fui eu quem fez o trabalho, foi outra pessoa da minha equipe, mas acho que acertei os detalhes mais importantes.A outra opção que eu estava considerando (antes de meu colega de equipe assumir) era chamar a API WSS4J diretamente para construir o envelope SOAP conforme o serviço .NET esperava.Acho que isso também teria funcionado.

Outras dicas

As especificações WS-Security normalmente não estão contidas em um WSDL (nunca em um WSE WSDL).Portanto, wsdl2java não sabe que o WS-Security é necessário para este serviço.O fato de restrições de segurança não estarem presentes em um WSDL WSE é uma grande decepção para mim (o WCF incluirá informações WS-Trust em um WSDL).

No lado do cliente, você precisará usar Muralha para incluir os cabeçalhos WS-Security necessários na mensagem do cliente de saída.Como o WSDL não informa quais configurações de WS-Security são necessárias, é melhor perguntar ao provedor de serviços o que é necessário.Os requisitos de segurança WS podem ser uma senha simples em texto simples, ou podem ser certificados X509, ou podem ser mensagens criptografadas.....Rampart deve ser capaz de lidar com a maioria desses cenários.

O Apache Rampart é "ligado" ao envolver o módulo em seu arquivo axis2.xml.Você precisará baixar o módulo Rampart e colocá-lo em um local específico no diretório axis2 e, em seguida, modificar o arquivo xml.Você também pode envolver o Rampart programaticamente (edite sua pergunta original se isso for um requisito e eu editarei esta resposta).

Dependendo de como você configura o rampart (através de outros arquivos XML ou programaticamente), ele interceptará quaisquer mensagens de saída e incluirá as informações necessárias do WS-Security nela.Eu pessoalmente usei o axis2 com o rampart para chamar um serviço WSE3 que é protegido com UsernameToken em texto simples e funcionou muito bem.Cenários semelhantes, mas mais avançados, também devem funcionar.Há mais detalhes sobre como configurar e começar a usar o Rampart no site com link acima.Se você tiver problemas sobre as especificidades do Rampart ou como usar o Rampart com sua configuração WSE específica, edite sua pergunta e tentarei responder ao máximo.

@Mike

Recentemente fiz um teste e este é o código que usei.Não estou usando políticas, mas usei WS-Security com autenticação de texto simples.O CXF tem uma documentação muito boa sobre como realizar essas coisas.

Usei wsdl2java e adicionei este código para usar o serviço web com ws-security.

Espero que isso ajude você.

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.handler.WSHandlerConstants;

public class ServiceTest implements CallbackHandler
{

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

            WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
            // set the password for our message.
            pc.setPassword("buddah");
        }

    public static void main(String[] args){
        PatientServiceImplService locator = new PatientServiceImplService();
        PatientService service = locator.getPatientServiceImplPort();

        org.apache.cxf.endpoint.Client client = org.apache.cxf.frontend.ClientProxy.getClient(service);
        org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();

        Map<String, Object> outProps = new HashMap<String, Object>();
        outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN + " " +  WSHandlerConstants.TIMESTAMP);
        outProps.put(WSHandlerConstants.USER, "joe");
        outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);

        // Callback used to retrieve password for given user.
        outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ServiceTest.class.getName());

        WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
        cxfEndpoint.getOutInterceptors().add(wssOut);


        try
        {
            List list = service.getInpatientCensus();
            for(Patient p : list){
                System.out.println(p.getFirstName() + " " + p.getLastName());
            }

        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

CXF - Eu daria uma olhada no CXF.Eu usei-o para criar um serviço web e cliente em java usando ws-secuirty.Também conectei um serviço da web .net a ele.

Eles também têm uma documentação muito boa.Tive mais sorte com isso do que com o eixo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top