Ejemplo de Web Service con CXF y certificado en el servidor

De ChuWiki

Veamos un ejemplo sencillo de cómo levantar un web service en java usando CXF y que tenga https. Tienes el ejemplo completo en cxf-server-https

Dependencias[editar]

Necesitas las siguiente dependencias (formato gradle)

    compile group: 'javax', name: 'javaee-api', version: '7.0'
    compile group: 'org.apache.cxf', name: 'cxf-rt-frontend-jaxws', version: '3.4.0'
    compile group: 'org.apache.cxf', name: 'cxf-rt-transports-http', version: '3.4.0'
    compile group: 'org.apache.cxf', name: 'cxf-rt-transports-http-jetty', version: '3.4.0'

El ejemplo es con un servidor jetty embebido, de ahí la dependencia. Si eliges otro tipo de servidor puede que el código cambie un poco. Aquí tienes el build.gradle compoleto.

Certificado del servidor[editar]

Para tener https, necesitamos un certificado en el servidor. Puedes usar este serverKey.jks que es el que se usa en el ejemplo. Este certificado usa formato PKCS12 y las passwords son changeit. Si usas otro tipo de certificado o passwords, tendrás que cambiarlo en el código.

En el apartado Creación del certificado de cliente/servidor tienes cómo crear un certificado usando la herramienta keytool de java. Por defecto, el tipo de almacenamiento es JKS, si quieres PKCS12, tienes que añadir la opción -storetype PKCS12

keytool -genkey -keyalg RSA -storetype PKCS12 -alias serverKay -keystore serverKey.jks -storepass servpass 


Si dejas la opción por defecto JKS, en el código de Main.java tendrás que cambiar PKCS12 por JKS.

El Web Service[editar]

En el ejemplo se ha hecho una calculadora sencilla, con las cuatro operaciones de sumar, restar, multiplicar y dividir. Lleva una interface Calculadora.java con la anotación @WebService y una clase CalculadoraImpl.java que lo implementa. Salvo la anotación todo es java normalito.

El Main[editar]

El código básico de Main.java es el siguiente

public static void main(String[] args) throws Exception {
        coinfigureJettyTLs();

        JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean();
        svrFactory.setServiceClass(Calculadora.class);
        svrFactory.setAddress("https://localhost:9443/Calculadora");
        svrFactory.setServiceBean(new CalculadoraImpl());
        svrFactory.create();
    }


El segundo bloque de código es el estándar de CXF para levantar un web service. Unicamente advertir que le hemos puesto una URL con https.

La primera llamada a coinfigureJettyTLs() es donde está toda la magia para leer el certificado y configurar al jetty embebido con él. El código es el siguiente

    private static String KEY_STORE_PATH_NAME = "serverKey.jks";
    private static String KEY_STORE_PASSWORD = "changeit";
    private static String PRIVATE_KEY_PASSWORD = "changeit";

    ...

    public static void coinfigureJettyTLs() throws Exception {
        /*
         * create a JettyHTTPServerEngineFactory to handle the configuration of
         * network port numbers for use with "HTTPS"
         */
        JettyHTTPServerEngineFactory jettyHTTPServerEngineFactory = new JettyHTTPServerEngineFactory();

        // load the key store containing the server certificate
        File keyStoreFile = new File(KEY_STORE_PATH_NAME);
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(new FileInputStream(keyStoreFile),
                KEY_STORE_PASSWORD.toCharArray());

        // create a key manager to handle the server private/public key pair
        KeyManagerFactory keyManagerFactory = KeyManagerFactory
                .getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, PRIVATE_KEY_PASSWORD.toCharArray());
        KeyManager[] keyManager = keyManagerFactory.getKeyManagers();

        // set the TLSServerParameters on theJettyHTTPServerEngineFactory
        TLSServerParameters tLSServerParameters = new TLSServerParameters();
        tLSServerParameters.setKeyManagers(keyManager);
        jettyHTTPServerEngineFactory.setTLSServerParametersForPort(9443,
                tLSServerParameters);
    }

Se obtiene un JettyHTTPServerEngineFactory para manejar la configuración de jetty.

Se lee el fichero del certificado y se guarda en un keyStore

Se crea un KeyManagerFactory para almacenar el certificado KeyStore leído.

Y finalmente se construye un TLSServerParameters donde almacenamos el keyManager y se lo pasamos al jettyHTTPServerEngineFactory indicando en qué puerto debe mostrar dicho certificado.

Fijate que el path del certificado hemos puesto sólo el nombre del fichero de certifiado. Esto implica que cuando ejecutes el programa, el fichero de certificado debe estar en el directorio de ejecución. Si no es así, debes poner un PATH adecuado con el nombre del fichero.

Prueba[editar]

Para poder probar este web service, puedes bajarte la aplicación sopaui. Una vez descargada y abierta, dale al botón "SOAP" para crear un nuevo proyecto. Te debería salir una ventana como esta



En el formulario, rellena Initial WSDL con la url de tu webservice añadiendo detrás ?wsdl. Nada más rellenar este campo, se rellenarán el resto. Así que solo darle Ok.

En el árbol de proyecto si lo vas deplegando, debería salirte la calculadora con todas sus operaciones. Doble click en una de las operaciones y te saldrá una ventana con dos paneles, el de la izquierda relleno, el de la derecha vacío. El de la izquierda es la petición XML que vas a hacer, verás que los dos valores que quieres operar (sumar en el caso de la figura), aparecen con interrogante. Debes reemplazar el interrogante por los valores que quieras. Luego, dando al botón triángulo verde, se hará la llamada al web service con lo que has indicado y verás el resultado en el lado derecho.

La siguiente imagen muestra el final de todo este proceso