Domanda

Devo chiamare un servizio web scritto in .NET da Java.Il servizio web implementa lo stack WS-Security (WSE 2 o WSE 3, non è chiaro dalle informazioni in mio possesso).

Le informazioni che ho ricevuto dal fornitore di servizi includevano WSDL, un file policyCache.config, codice C# di esempio e un'applicazione di esempio in grado di chiamare correttamente il servizio.

Questo non è così utile come sembra perché non è chiaro come dovrei usare queste informazioni per scrivere un client Java.Se la richiesta del servizio Web non è firmata secondo la policy, viene rifiutata dal servizio.Sto cercando di utilizzare Apache Axis2 e non riesco a trovare alcuna istruzione su come dovrei utilizzare il file policyCahce.config e il WSDL per generare un client.

Ci sono diversi esempi che ho trovato sul Web ma in tutti i casi gli autori degli esempi avevano il controllo sia del servizio che del client e quindi erano in grado di apportare modifiche su entrambi i lati per farlo funzionare.Non sono in quella posizione.

Qualcuno lo ha fatto con successo?

È stato utile?

Soluzione 2

Questa sembra essere una domanda popolare, quindi fornirò una panoramica di ciò che abbiamo fatto nella nostra situazione.

Sembra che i servizi integrati in .NET seguano uno standard di indirizzamento ws precedente (http://schemas.xmlsoap.org/ws/2004/03/addressing/) e axis2 comprende solo lo standard più recente (http://schemas.xmlsoap.org/ws/2004/08/addressing/).

Inoltre, il file policyCache.config fornito è in un formato che il modulo axis2 rampart non è in grado di comprendere.

Quindi i passaggi che dovevamo fare, in poche parole:

  • Leggi policyCache.config e prova a capirlo.Quindi riscriverlo in una politica che Bastione possa comprendere.(Alcuni documenti aggiornati aiutato.)
  • Configura rampart con questa policy.
  • Prendi le chiavi fornite nel file .pfx e convertile in un archivio chiavi Java.C'è un'utilità fornita con Jetty che può farlo.
  • Configura il bastione con quell'archivio chiavi.
  • Scrivi un gestore asse2 personalizzato che converte all'indietro il materiale di indirizzamento ws più recente che esce da asse2 nel materiale più vecchio previsto dal servizio.
  • Configura asse2 per utilizzare il gestore sui messaggi in uscita.

Alla fine si è trattato di un sacco di configurazione e codice per qualcosa che dovrebbe essere uno standard aperto supportato dai fornitori.

Anche se non sono sicuro di quale sia l'alternativa... puoi aspettare che i fornitori (o in questo caso, l'unico fornitore) si assicurino che tutto funzioni in modo interoperabile?

Come post scriptum aggiungerò che alla fine non sono stato io a fare il lavoro, è stato qualcun altro nel mio team, ma penso di aver capito correttamente i dettagli salienti.L'altra opzione che stavo prendendo in considerazione (prima che il mio compagno di squadra subentrasse) era chiamare direttamente l'API WSS4J per costruire la busta SOAP come previsto dal servizio .NET.Penso che anche questo avrebbe funzionato.

Altri suggerimenti

Le specifiche WS-Security non sono generalmente contenute in un WSDL (mai in un WSDL WSE).Quindi wsdl2java non sa nemmeno che WS-Security è necessario per questo servizio.Il fatto che i vincoli di sicurezza non siano presenti in un WSDL WSE è per me una grande delusione (WCF includerà le informazioni WS-Trust in un WSDL).

Sul lato client, dovrai utilizzare Bastione per aggiungere le intestazioni WS-Security necessarie al messaggio client in uscita.Poiché WSDL non segnala quali impostazioni WS-Security sono necessarie, è meglio chiedere al fornitore di servizi cosa è richiesto.I requisiti WS-Security possono essere semplici password in testo normale, certificati X509 o messaggi crittografati.Rampart dovrebbe essere in grado di gestire la maggior parte di questi scenari.

Apache Rampart viene "attivato" inserendo il modulo nel file axis2.xml.Dovrai scaricare il modulo Rampart e inserirlo in una posizione specifica nella directory axis2, quindi modificare il file xml.Puoi anche coinvolgere Rampart in modo programmatico (modifica la tua domanda originale se questo è un requisito e io modificherò questa risposta).

A seconda di come si configura rampart (tramite altri file XML o in modo programmatico), intercetterà qualsiasi messaggio in uscita e vi aggiungerà le informazioni WS-Security necessarie.Personalmente ho utilizzato axis2 con rampart per chiamare un servizio WSE3 protetto con UsernameToken in testo normale e ha funzionato benissimo.Dovrebbero funzionare anche scenari simili, ma più avanzati.Sono disponibili maggiori dettagli su come configurare e iniziare con Rampart sul sito collegato sopra.Se hai problemi sulle specifiche di Rampart o su come utilizzare Rampart con la tua particolare configurazione WSE, modifica la tua domanda e farò del mio meglio per rispondere.

@Mike

Recentemente ho fatto un test e questo è il codice che ho usato.Non sto utilizzando elementi di policy, ma ho utilizzato WS-Security con autenticazione in testo semplice.CXF ha un'ottima documentazione su come realizzare queste cose.

Ho usato wsdl2java e poi ho aggiunto questo codice per utilizzare il servizio web con ws-security.

Spero che questo ti aiuti.

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 - Io esaminerei CXF.L'ho usato per creare un servizio web e un client in Java utilizzando ws-secuirty.Ad esso ho anche collegato un servizio Web .net.

Hanno anche una documentazione abbastanza buona.Ho avuto più fortuna con esso che con l'asse.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top