Client e Server, struttura dei progetti
Riprendendo il discorso affrontato nel capitolo precedente, in entrambi i casi analizzati possiamo utilizzare i progetti realizzati apportando piccole modifiche.
Il progetto del server
Per il server, occorrerà modificare il file jbossws-cxf.xml
come già descritto. Occorrerà inoltre importare nella cartella WEB-INF
i file serverwssec.properties
e serverwssec.jks
. Occorrerà infine modificare l’implementazione del CallbackHandler
già presente.
In questo esempio invece di modificare la vecchia implementazione KeystorePasswordCallback
si è preferito far puntare gli interceptors alla una nuova classe KeystorePasswordCallbackComplete
descritta di seguito. Sarà compito del file jbossws-cxf.xml
puntare all’implementazione scelta.
package test.security;
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.ws.security.WSPasswordCallback;
public class KeystorePasswordCallbackComplete implements CallbackHandler{
private Map<String, String> passwords = new HashMap<String, String>();
public KeystorePasswordCallbackComplete(){
passwords.put("serverwssec", "password");
passwords.put("bob", "password");
}
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException{
for (int i = 0; i < callbacks.length; i++){
WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
String pass = passwords.get(pc.getIdentifer());
if (pass != null)
{
pc.setPassword(pass);
return;
}
}
}
}
Il progetto del client
Per il server non occorre altro. Passando al progetto del client, per prima cosa possiamo includere la classe KeystorePasswordCallbackComplete
, lasciandone invariato anche il package test.security
. Successivamente si potranno importare i file bob.jks
e bob.properties
memorizzandoli all’interno della cartella META-INF
. A questo punto possiamo aggiungere un main nel quale forniremo i parametri per gli interceptors.
package wsClient;
import java.util.HashMap;
import java.util.Map;
import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor;
import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
import test.documento.prova.ServizioPresentazioneIF;
public class ServizioClientWSSecComplete {
public static void main(String[] args) {
String prot = "http";
String host = "localhost";
String port = "8080";
String protHostPort = prot+"://"+host+":"+port;
ClientMETAInf sensorClient = new ClientMETAInf(null);
ServizioPresentazioneIF servicePort = sensorClient.getServicePort(protHostPort);
Client client = ClientProxy.getClient(servicePort);
Endpoint cxfEndpoint = client.getEndpoint();
Map<String,Object> outProps = new HashMap<String,Object>();
outProps.put("action", "Timestamp Signature Encrypt");
outProps.put("user", "bob");
outProps.put("signaturePropFile", "META-INF/bob.properties");
outProps.put("signatureKeyIdentifier", "DirectReference");
outProps.put("passwordCallbackClass", "test.security.KeystorePasswordCallbackComplete");
outProps.put("signatureParts", "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body");
outProps.put("encryptionPropFile", "META-INF/bob.properties");
outProps.put("encryptionUser", "serverwssec");
outProps.put("encryptionParts", "{Element}{http://www.w3.org/2000/09/xmldsig#}Signature;{Content}{http://schemas.xmlsoap.org/soap/envelope/}Body");
outProps.put("encryptionSymAlgorithm", "http://www.w3.org/2001/04/xmlenc#tripledes-cbc");
outProps.put("encryptionKeyTransportAlgorithm", "http://www.w3.org/2001/04/xmlenc#rsa-1_5");
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps); //request
cxfEndpoint.getOutInterceptors().add(wssOut);
cxfEndpoint.getOutInterceptors().add(new SAAJOutInterceptor());
Map<String,Object> inProps= new HashMap<String,Object>();
inProps.put("action", "Timestamp Signature Encrypt");
inProps.put("signaturePropFile", "META-INF/bob.properties");
inProps.put("passwordCallbackClass", "test.security.KeystorePasswordCallbackComplete");
inProps.put("decryptionPropFile", "META-INF/bob.properties");
WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps); //response
cxfEndpoint.getInInterceptors().add(wssIn);
cxfEndpoint.getInInterceptors().add(new SAAJInInterceptor());
String nome = "Micky";
String cognome = "Mouse";
System.out.println(nome+" "+cognome+" effettua la presentazione. ");
String risposta=servicePort.presentazione(nome, cognome);
System.out.println("Risposta ottenuta: "+risposta);
}
}
Il main ricalca in modo speculare quanto abbiamo già visto nel jbossws-cxf.xml
. Viene impostato un endpoint CXF che punta al servizio. All’endpoint vengono quindi aggiunti due interceptors, uno in ingresso e uno in uscita in modo simile a quanto già fatto per il server, entrambi legati al CallbackHandler implementato.
E’ possibile osservare le properties settate per criptare con RSA e firmare con il Triple DES. Anche in questo caso per il client sono state sufficienti le sole librerie dello stack CXF, mentre non sono risultate necessarie librerie del framework Spring.