Servicios Web Java: Firma y cifrado de WS-Security de Axis2

Aprenda cómo usar Axis2 y Rampart para firmar y cifrar mensajes

Obtenga una introducción a los principios de la criptografía de clave pública, luego vea cómo el WS-Security los aplica para firmar y cifrar mensajes SOAP usando pares de claves públicas-privadas en combinación con claves secretas. Dennis Sosnoski continúa su Servicios Web Java serie de servicios web Java con una discusión sobre recursos WS-Security y WS-SecurityPolicy de firma y cifrado, junto con código de ejemplo usando Axis2 y Rampart.

Dennis Sosnoski, Architecture Consultant and Trainer, Sosnoski Software Solutions, Inc.

Author photoDennis Sosnoski es consultor y capacitador especializado en XML y servicios web basados en Java. Su experiencia profesional en desarrollo de software abarca más de 30 años, y en los últimos 10 años se ha enfocado en tecnologías XML y Java. Dennis es desarrollador líder de la infraestructura JiBX XML Data Binding de fuente abierta y de la infraestructura JiBX/WS de servicios web asociada, así como committer en la infraestructuraApache Axis2 de servicios web. Él también fue uno de los miembros del Grupo de Expertos para las especificaciones JAX-WS 2.0 y JAXB 2.0. El material para la serie de Servicios Web Java se basa en las clases de capacitación de Dennis.



16-01-2012

La seguridad es crucial cuando los servicios web intercambian datos de negocios. Si los datos son interceptados por terceros esto puede tener consecuencias financieras o legales negativas, o si se aceptan datos fraudulentos como válidos. Siempre es posible diseñar e implementar el manejo de seguridad propio de cada aplicación para servicios web — como para cada forma de intercambio de datos— pero ese es un enfoque arriesgado, porque incluso una pequeña y oscura omisión puede conducir a serias vulnerabilidades. Uno de los principales beneficios de SOAP en comparación con formas más simples es que permite extensiones modulares. La seguridad ha sido un enfoque principal para extensiones casi desde el release inicial de SOAP, dando como resultado la estandarización de WS-Security y las tecnologías relacionadas que permiten que la seguridad sea configurada para cada servicio según sea apropiado.

Los requisitos de seguridad en el intercambio de información generalmente cubren tres aspectos:

  • Confidencialidad: Solo el destinatario pretendido de un mensaje tiene acceso al contenido del mensaje.
  • Integridad: El mensaje es recibido sin notificación.
  • Autenticidad: El origen del mensaje puede ser verificado.

WS-Security le permite responder fácilmente a todos los tres aspectos. En este artículo, usted verá cómo hacer esto usando Axis2 y la extensión Rampart WS-Security. Pero primero, le presentaré un repaso rápido sobre los principios del cifrado de clave pública — la base de la mayoría de los recursos de cifrado y firma WS-Security.

Sobre esta serie

Los servicios web son una parte crucial del rol de la™ tecnología Java en la computación corporativa. En esta serie de artículos, el consultor de servicios XML y servicios web Dennis Sosnoski cubre las principales infraestructuras y tecnologías que son importantes para desarrolladores Java que usen servicios web. Siga la serie para permanecer informado sobre los últimos desarrollos en el área y esté al tanto sobre cómo puede usarlos para saber cómo apoyarse en sus proyectos de programación.

Criptografía de clave pública

Durante la mayor parte de la historia el intercambio seguro de mensajes se ha basado en alguna forma de secreto compartido. El secreto puede tomar la forma de código, en donde las partes del intercambio tienen un conjunto de sustituciones de frases o acciones que han acordado previamente. O puede ser un cifrado, en donde el texto es convertido en otro texto usando algún algoritmo. El secreto puede incluso tomar otras formas, como un lenguaje desconocido para otros que puedan haber accedido a los mensajes. El secreto compartido hizo que el intercambio del mensaje fuera seguro. No obstante, si alguna parte descubrió el secreto, el intercambio de mensaje puede haberse comprometido, con resultados potencialmente devastadores para las partes que hacen el intercambio. (Piense en Enigma y las comunicaciones militares alemanas durante la II Guerra Mundial, por ejemplo).

La criptografía de clave pública es un enfoque inherentemente a la seguridad, que no requiere un secreto compartido. Está basada en la idea de las funciones matemáticas de "trampilla", las cuales son fáciles de computar en una dirección pero difíciles de computar en la dirección inversa. Por ejemplo, es fácil encontrar el producto de dos números primos (incluso primos bastante grandes, si está trabajando en una computadora), pero es mucho más difícil analizar ese producto para encontrar los dos factores originales. Si usted construye un algoritmo de cifrado en torno a la dirección fácil de una función, cualquiera que espere romper su cifrado necesita trabajarlo desde el lado difícil. Y con un algoritmo bien elegido, la tarea de romper un cifrado puede ser tan difícil que no es práctico hacerlo en un lapso de tiempo que amenace el intercambio del mensaje (al menos hasta que alguién desarrolle una computadora cuántica usable o capacidades muy buenas).

Con la criptografía de clave pública, una parte que desee recibir mensajes cifrados crea un par de valores clave. Cada valor clave puede usarse de forma separada para cifrar mensajes, pero no puede usarse para descifrar los mensajes que se usó para cifrar. En lugar de ello, el otro valor de la pareja debe utilizarse para el descifrado. Siempre que el propietario de la clave mantenga alguna de las claves en secreto, la otra clave se puede hacer pública. Cualquiera con acceso a la clave pública puede usarla para cifrar mensajes, lo cual puede luego ser descifrado solo por el propietario de la clave. Como las claves separadas se utilizan para cifrar y descifrar mensajes, esta forma de criptografía es llamada cifrado asimétrico.

Firmando mensajes

Cuando su clave pública es usada para cifrar un mensaje, solo usted (como poseedor de la llave privada) puede descifrar ese mensaje. Esto asegura la confidencialidad, uno de los tres aspectos del intercambio seguro de mensajes. Pero también es posible usar su claveprivada para cifrar un mensaje, y cuando esto se hace, cualquiera con una copia de su clave pública puede descifrar ese mensaje. Esto parece no ser muy útil inicialmente — ¿qué tan bueno es un mensaje cifrado que cualquiera puede leer? — pero sirve bien como forma de verificar la autenticidad del mensaje. Alguien que recibe un mensaje cifrado que supuestamente proviene de usted puede usar su clave pública para descifrar el mensaje y compararlo con algún valor esperado. Si el resultado coincide, sabrán que usted creó el mensaje.

En la práctica, en la firma de mensajes es más lo que está involucrado que simplemente cifrar con su clave privada. Usted necesita alguna forma de establecer el valor esperado del mensaje descifrado, por una cosa. Esto generalmente se hace usando otra variación de la función matemática de trampilla: una función hash que es fácil de computar pero difícil de duplicar (lo cual quiere decir que es difícil hacer cualquier cambio a un mensaje sin cambiar el valor hash para ese mensaje, o encontrar otro mensaje con el mismo valor hash que el mensaje suministrado). Con tal función hash, usted puede generar el valor hash (generalmente llamado resumen en discusiones de seguridad) para el mensaje que usted desee firmar, luego cifrar ese resumen usando su clave privada y enviar el valor de resumen cifrado con el mensaje. Cualquiera que reciba el mensaje puede usar el mismo algoritmo hash de ese mensaje, luego descifrar el resumen cifrado suministrado usando su clave pública y comparar ambos valores. Si los valores coinciden, entonces el receptor puede estar seguro (dentro de los límites de la tecnología actual) de que ese mensaje es de usted.

Hay otro paso que está involucrado en la firma de mensajes cuando usted está tratando con XML. Los mensajes XML son expresados en forma de texto, pero algunos de los aspectos de la representación de texto son considerados irrelevantes por XML (como el orden de los atributos en un elemento o espacio en blanco usado dentro de una etiqueta de inicio o finalización de un elemento). Debido a este problema con la representaciones de texto, el W3C (propietario de la especificación) decidió convertir mensajes XML hacia una forma de texto canónico antes de computar un valor de resumen (vea Recursos). Con XML se pueden usar varios algoritmos de canonicalización, los cuales no pueden usarse con mensajes XML. El algoritmo particular usado generalmente no importa mucho, siempre que ambas propiedades que participan en un intercambio de mensaje estén de acuerdo en usar el mismo.

Usar un resumen de mensaje firmado garantiza tanto integridad de mensaje (porque las modificaciones al mensaje cambiarán el valor de resumen) como de autenticidad (porque su clave privada es usada para cifrar el resumen). Como la confidencialidad es garantizada para los mensajes enviados a usted mediante cifrado que usa su clave privada, todos los aspectos principales de la seguridad de intercambio de mensajes están cubiertos al usar un par de claves pública-privada. Desde luego, con el par de clave individual solo se asegura una dirección de un intercambio de mensaje — pero si la otra parte del intercambio también tiene su propio par de clave pública/privada, se puede proporcionar seguridad privada completa para mensajes que van en cada dirección.

Certificados

Así, las claves públicas-privadas pueden utilizarse tanto para cifrado como para firma de mensajes intercambiados entre dos partes, siempre y cuando cada parte tenga acceso a la clave pública de la otra. Eso deja el problema de cómo obtiene usted la clave pública de una forma que mantenga la seguridad. Entre las diferentes formas de hacer esto, la más ampliamente utilizada es tener hacer que uno o más terceros avalen la clave pública. Los certificados digitales son el mecanismo para proporcionar claves públicas de esta forma por aval.

Un certificado digital es básicamente un empaquetador en torno a una clave pública, que incluye identificar información para la parte que es propietaria de esa clave. Este cuerpo empaquetado es luego firmado por un tercero y la firma es incluida en el certificado. El tercero confiable avala la clave pública e identifica la información emitiendo el certificado con su firma. Desde luego, esto deja el problema del programa de arranque de cómo establece usted la identidad del tercero. Esto generalmente se hace con código intensivo en los certificados para ciertos terceros confiables llamadas autoridades emisoras dentro del software (como la JVM).

Hay mucho más en cuanto a los certificados digitales que va más allá de los fundamentos descritos aquí, incluyendo formas de revocar certificados emitidos por error (lo cual, desafortunadamente, sucede) o con claves privadas comprometidas, hay veces en que el certificado es válido y extensiones para especificar el uso pretendido del certificado. Consulte Recursos para enlaces hacia más información sobre certificados digitales y cifrado de claves públicas en general. También puede consultar la documentación para la herramienta de seguridad keytool incluida en su instalación JDK. La documentación de keytool le ofrece una buena introducción a la estructura y el manejo de certificados, junto con almacenes de claves (que se tratan a continuación) y otros aspectos de la seguridad. Más adelante en este artículo también verá un ejemplo de trabajo con la keytool.

Almacenes de claves

La mayoría del código de seguridad Java funciona con claves privadas y certificados digitales usando almacenes de claves. Un almacén de claves es un archivo que contiene entradas de clave y certificado de forma cifrada. Se requiere de una contraseña para acceder a un almacén de claves. Cada clave privada del almacén de claves es cifrada nuevamente, requiriendo una contraseña adicional, con el fin de ayudar a mantener la seguridad de las claves. Cualquier software que use el almacén de claves y claves privadas necesita tener contraseñas tanto de almacén de claves y de clave privada al momento del tiempo de ejecución. Esto limita la seguridad proporcionada por estas contraseñas (porque cualquiera con acceso al código fuente puede descubrir cómo se cargan las contraseñas). Así, usted necesita mantener una seguridad física del sistema que hospeda el software y de cualquier copia de seguridad para ese sistema. Y usted debe mantener el almacén de claves y la contraseña solo en ese sistema y aquellas copias de seguridad con el fin de mantener seguras sus claves privadas.

Claves secretas y cifrado simétrico

Aunque la criptografía de clave pública usando cifrado simétrico es la base para muchos de los recursos útiles de WS-Security, la criptografía de clave secreta tradicional todavía juega un papel importante. Los algoritmos de cifrado asimétrico tienden a ser mucho más intensivos computacionalmente que los algoritmos simétricos basados en claves secretas (en donde la misma clave es usada tanto para cifrar como para descifrar, lo cual significa que la clave debe permanecer en secreto) para niveles de protección equivalentes. Por esta razón, las dos técnicas a menudo se usan en combinación: el cifrado asimétrico de alto costo se utiliza para salvaguardar el intercambio de una clave secreta, la cual puede luego ser usada para cifrado simétrico de bajo costo. Usted verá un ejemplo de este enfoque más adelante en el artículo, cuando observe el cifrado WS-Security de un mensaje.


Configurando

Este artículo usa la misma aplicación de ejemplo que "Axis2 WS - Fundamentos de seguridad", el cual muestra cómo implementar el UsernameToken de WS-Security usando Axis2 y Rampart. Sin embargo, son necesarios algunos cambios para soportar el uso de recursos de criptografía de clave pública WS-Security, por lo que un paquete de código aparte acompaña este artículo (vea Descargas).

El directorio raíz del código de ejemplo es jws05code. Dentro de este directorio usted encontrará:

  • Un archivo Ant build.xml
  • Un archivo Ant build.properties, que configura el funcionamiento de la aplicación de ejemplo
  • El archivo library.wsdl que da la definición de servicio para la aplicación de ejemplo
  • Un archivo log4j.properties usado para configurar el registro del lado del cliente
  • Varios archivos XML de definición de propiedades (todos llamados XXX-policy-client.xml o XXX-policy-server.xml)

Antes de que usted pueda comprar el código de ejemplo, necesitará:

  1. Editar el archivo build.properties para configurar la ruta para su instalación Axis2.
  2. Asegurarse de que su instalación Axis2 haya sido actualizada con el código Rampart, como se trató en la sección Instalando Rampart de "Axis2 WS - Fundamentos de seguridad." (Una buena forma de verificar es observando en el directorio de repositorio/módulos en busca de un archivo de módulo rampart-x.y.mar).
  3. Añadir el proveedor de seguridad org.bouncycastle.jce.provider.BouncyCastleProvider Bouncy Castle (necesario para los recursos de criptografía de clave pública usados en el código de ejemplo) para su configuración de seguridad JVM (el archivo lib/security/java.security) (vea Recursos).
  4. Añadir el JAR Bouncy Castle (llamado bcprov-jdkxx-vvv.jar, donde xx es su versión de Java y vvv es la versión de código Bouncy Castle) tanto para el directorio de biblioteca de su instalación Axis2 como para su directorio WEB.INF/de biblioteca de aplicaciones de su servidor Axis2.

Ahora usted está listo para construir la aplicación de ejemplo y para intentar los ejemplos de seguridad que se tratan en las siguientes secciones.


Firmando mensajes

Firmar mensajes requiere de mucha más especificación que el ejemplo UsernameToken en "Axis2 WS - Fundamentos de seguridad." Usted necesita:

  • Identificar el par de claves privada/pública que se utiliza para crear la firma en cada dirección, y proporcionar las contraseñas usadas para acceder al almacén de claves y la clave privada.
  • Especificar el conjunto de algoritmos usados para la canonicalización, generación de resúmenes y firma efectiva.
  • Especificar cuáles porciones del mensaje se van a incluir en la firma.

Parte de esta información es manejada como datos de configuración, incorporados en el documento WS-SecurityPolicy para el servicio. Otras partes están incluidas en el intercambio de mensaje de tiempo de ejecución.

El Listado 1 muestra un documento WS-Policy usado para configurar el cliente Axis2 para firmar mensajes. (El Listado 1 se ha editado para que se ajuste a la página. Vea todo el texto como sign-policy-client.xml en el código de ejemplo).

Listado 1. WS-Policy/WS-SecurityPolicy para firmas (cliente)
<!-- Client policy for signing all messages, with certificates included in each
 message -->
<wsp:Policy wsu:Id="SignOnly"
    xmlns:wsu="http://.../oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
  <wsp:ExactlyOne>
    <wsp:All>
      <sp:AsymmetricBinding
          xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
        <wsp:Policy>
          <sp:InitiatorToken>
            <wsp:Policy>
              <sp:X509Token
                  sp:IncludeToken="http://.../IncludeToken/AlwaysToRecipient"/>
            </wsp:Policy>
          </sp:InitiatorToken>
          <sp:RecipientToken>
            <wsp:Policy>
              <sp:X509Token
                  sp:IncludeToken="http://.../IncludeToken/AlwaysToInitiator"/>
            </wsp:Policy>
          </sp:RecipientToken>
          <sp:AlgorithmSuite>
            <wsp:Policy>
              <sp:TripleDesRsa15/>
            </wsp:Policy>
          </sp:AlgorithmSuite>
          <sp:Layout>
            <wsp:Policy>
              <sp:Strict/>
            </wsp:Policy>
          </sp:Layout>
          <sp:IncludeTimestamp/>
          <sp:OnlySignEntireHeadersAndBody/>
        </wsp:Policy>
      </sp:AsymmetricBinding>
      <sp:SignedParts xmlns:sp="http://.../ws-securitypolicy/200702">
        <sp:Body/>
      </sp:SignedParts>

      <ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
        <ramp:user>clientkey</ramp:user>
        <ramp:passwordCallbackClass
            >com.sosnoski.ws.library.adb.PWCBHandler</ramp:passwordCallbackClass>

        <ramp:signatureCrypto>
          <ramp:crypto provider="org.apache.ws.security.components.crypto.Merlin">
            <ramp:property name="org.apache.ws.security.crypto.merlin.keystore.type"
                >JKS</ramp:property>
            <ramp:property name="org.apache.ws.security.crypto.merlin.file"
                >client.keystore</ramp:property>
            <ramp:property
                name="org.apache.ws.security.crypto.merlin.keystore.password"
                >nosecret</ramp:property>
          </ramp:crypto>
        </ramp:signatureCrypto>

      </ramp:RampartConfig>

    </wsp:All>
  </wsp:ExactlyOne>
</wsp:Policy>

En el Listado 1, el elemento <sp:AsymmetricBinding> de la política proporciona la información de configuración básica para el uso de criptografía de clave pública en el intercambio de mensaje. Dentro de este elemento se utilizan diversos elementos anidados para lo específico de la configuración. El <sp:InitiatorToken> identifica el par de claves usadas para firmar mensajes desde el cliente (el iniciador) hacia el servidor (el receptor), declarando en este caso que la clave pública estará en forma de un certificado X.509 y que será enviada con cada menaje desde el cliente (sp:IncludeToken=".../AlwaysToRecipient"). El <sp:RecipientToken> identifica el par de claves usadas para firmar mensajes en la ruta de respuesta desde el servidor hacia el cliente, usando de nuevo un certificado X.509 y con el certificado incluido en cada menaje desde el servidor (sp:IncludeToken=".../AlwaysToInitiator").

El elemento <sp:AlgorithmSuite> identifica el conjunto de algoritmos usado para la firma. El <sp:IncludeTimestamp> informa que se utilizará una marca de tiempo con cada mensaje (útil para evitar ataques de tipo repetición sobre un servicio, mientras que un mensaje es capturado en tránsito y luego vuelto a presentar en un intento por confundir o romper el servicio). El elemento <sp:OnlySignEntireHeadersAndBody> dice que la firma se efectuará en todo el encabezado o cuerpo del mensaje, más que en algún elemento anidado (otra medida de seguridad, evitando ciertos tipos de ataques que reescriben el mensaje). El elemento <sp:SignedParts> identifica las partes del mensaje a ser firmadas — en este caso, el Cuerpo del mensaje SOAP.

La última parte del documento WS-Policy Listado 1 proporciona información de configuración específica de Rampart. Esta es una versión más compleja de la configuración Rampart usada en "Axis2 WS - Fundamentos de seguridad," incluyendo esta vez un elemento <ramp:user> p ara identificar la clave que se utilizará para firmar mensajes y un elemento<ramp:signatureCrypto> para configurar el almacén de claves que contiene la clave de cliente privado y el certificado de servidor. El almacén de claves referenciado debe estar presente en la ruta de acceso de clase en el tiempo de ejecución. En la aplicación de ejemplo, el archivo de almacén de claves es copiado en el directorio cliente/bin durante la creación.

Las clases de llamado de retorno de contraseña son un poco diferentes de las usadas en "Axis2 WS - Fundamentos de seguridad." Para ese artículo, el llamado de retorno de contraseña solo se necesitaba en el servidor y solo necesitaba verificarUsernameToken) o establecer (para un hash UsernameToken) la contraseña que coincidía con un nombre de usuario en particular. Para la criptografía de clave pública usada en este artículo, el llamado de retorno debe proporcionar la contraseña usada para proteger la clave dentro del almacén. Y los llamados de retorno separados son necesarios para el cliente (para proporcionar la contraseña para la clave privada del cliente) y el servidor (para proporcionar la contraseña para la clave privada de servidor). El Listado 2 muestra la versión del lado del cliente del llamado de retorno:

Listado 2. Llamado de retorno de contraseña del cliente
/**
 * Simple password callback handler. This just checks if the password for the private key
 * is being requested, and if so sets that value.
 */
public class PWCBHandler implements CallbackHandler
{
    public void handle(Callback[] callbacks) throws IOException {
        for (int i = 0; i < callbacks.length; i++) {
            WSPasswordCallback pwcb = (WSPasswordCallback)callbacks[i];
            String id = pwcb.getIdentifer();
            int usage = pwcb.getUsage();
            if (usage == WSPasswordCallback.DECRYPT ||
                usage == WSPasswordCallback.SIGNATURE) {

                // used to retrieve password for private key
                if ("clientkey".equals(id)) {
                    pwcb.setPassword("clientpass");
                }

            }
        }
    }
}

El llamado de retorno del Listado 2 está diseñado para soportar tanto la firma como el descifrado usando el mismo par de claves privadas-públicas, por lo que revisa para ambos casos y retorna la misma contraseña en cualquier caso.

Junto con la WS-Policy del Listado 1 usada para el cliente, hay una que coincide para el servidor (sign-policy-server.xml en el código de ejemplo) la cual difiere solo en los detalles de la configuración Rampart. De forma similar, la versión de servidor del llamado de retorno de contraseña del Listado 2 difiere solo en el valor identificador y en la contraseña retornada.

Ejecutando la aplicación de ejemplo

El archivo build.properties tiene líneas que referencian los archivos client.policy y server.policy a ser usados por la aplicación de ejemplo. estos son configurados respectivamente a sign-policy-client.xml y sign-policy-server.xml en la versión suministrada del archivo, por lo que usted solo necesita construir la aplicación. Usted puede hacer esto con Ant abriendo la consola en el directorio jws05code e ingresando ant. Si todo está configurado correctamente, usted deben terminar con un archivo de servicio library-signencr.aar Axis2 en el directorio jws05code. Implemente el servicio en su instalación de servidor Axis2 subiendo el archivo .aar usando la página administrativa Axis2, y luego intente el cliente ingresando ant run en la consola. Si todo se configuró correctamente, usted deberá ver el resultado mostrado en la Figura 1:

Figura 1. Resultado de consola por la ejecución de la aplicación
Resultado de consola por la ejecución de la aplicación

Para ver la información real WS-Security en los mensajes, usted necesita usar una herramienta como TCPMon (vea Recursos). Primero tenga el TCPMon configurado y aceptando conexiones desde el cliente en un puerto, las cuales luego reenvía hacia el servidor que se ejecuta en un puerto diferente (o en un host diferente). Luego puede editar el archivo build.properties y cambiar el valor del puerto host al puerto de escucha por TCPMon. Si usted ingresa de nuevo ant run en la consola, entonces verá los mensajes que se están intercambiando. El Listado 3 muestra una captura de ejemplo de mensaje-cliente:

Listado 3. Primer mensaje del cliente al servidor
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header>
    <wsse:Security xmlns:wsse=".../oasis-200401-wss-wssecurity-secext-1.0.xsd"
        soapenv:mustUnderstand="1">
      <wsu:Timestamp xmlns:wsu=".../oasis-200401-wss-wssecurity-utility-1.0.xsd"
          wsu:Id="Timestamp-3753023">
        <wsu:Created>2009-04-18T19:26:14.779Z</wsu:Created>
        <wsu:Expires>2009-04-18T19:31:14.779Z</wsu:Expires>
      </wsu:Timestamp>
      <wsse:BinarySecurityToken
          xmlns:wsu=".../oasis-200401-wss-wssecurity-utility-1.0.xsd"
          EncodingType=".../oasis-200401-wss-soap-message-security-1.0#Base64Binary"
          ValueType=".../oasis-200401-wss-x509-token-profile-1.0#X509v1"
          wsu:Id="CertId-2650016">MIICoDC...0n33w==</wsse:BinarySecurityToken>
      <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
          Id="Signature-29086271">
        <ds:SignedInfo>
          <ds:CanonicalizationMethod
              Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
          <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
          <ds:Reference URI="#Id-14306161">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <ds:DigestValue>SiU8LTnBL10/mDCPTFETs+ZNL3c=</ds:DigestValue>
          </ds:Reference>
          <ds:Reference URI="#Timestamp-3753023">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <ds:DigestValue>2YopLipLgBFJi5Xdgz+harM9hO0=</ds:DigestValue>
          </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>TnUQtz...VUpZcm3Nk=</ds:SignatureValue>
        <ds:KeyInfo Id="KeyId-3932167">
          <wsse:SecurityTokenReference
              xmlns:wsu=".../oasis-200401-wss-wssecurity-utility-1.0.xsd"
              wsu:Id="STRId-25616143">
            <wsse:Reference URI="#CertId-2650016"
              ValueType=".../oasis-200401-wss-x509-token-profile-1.0#X509v1"/>
          </wsse:SecurityTokenReference>
        </ds:KeyInfo>
      </ds:Signature>
    </wsse:Security>
  </soapenv:Header>
  <soapenv:Body
      xmlns:wsu=".../oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Id-14306161">
    <ns2:getBook xmlns:ns2="http://ws.sosnoski.com/library/wsdl">
      <ns2:isbn>0061020052</ns2:isbn>
    </ns2:getBook>
  </soapenv:Body>
</soapenv:Envelope>

El encabezado <wsse:Security> dentro del mensaje SOAP contiene toda la información de configuración de seguridad de tiempo de ejecución y los datos de firma. El primer elemento presentado es un <wsu:Timestamp>, como lo solicitó la configuración WS-SecurityPolicy. La marca de tiempo incluye dos valores de tiempo: el momento en el que el valor fue creado y el momento en el que expira. Estos dos valores están separados cinco minutos en este caso, que es lo predeterminado para Rampart. (Usted puede cambiar los valores como parte de la política de configuración Rampart). La cantidad de tiempo entre los dos es algo arbitraria, pero cinco minutos es un valor razonable — es lo suficientemente largo para sobrellevar una cantidad razonable de sesgo de reloj (diferencias entre los tiempos de reloj de sistema) entre el cliente y el servidor, mientras es lo suficientemente corto como para limitar el potencial para ataques de respuesta usando el mensaje. Después de la marca de tiempo, el siguiente elemento del encabezado es un <wsse:BinarySecurityToken>. Este token de seguridad es el certificado del cliente, en forma codificada binaria base64.

El tercer elemento del encabezado de seguridad es un bloque <ds:Signature> , con tres elementos hijos. El primer elemento hijo, <ds:SignedInfo>, es la única parte del mensaje que se firma directamente. El primer elemento hijo dentro del <ds:SignedInfo> identifica el algoritmo usado para su propia canonicalización y firma. Estos son seguidos por un elemento hijo <ds:Reference> para cada componente de mensaje incluido en la firma. Cada elemento hijo <ds:Reference> referencia un componente de mensaje particular mediante identificador y proporciona los algoritmos de canonicalización y resumen aplicados a ese componente, junto con el valor de resumen resultante. Los elementos hijos restantes de <ds:SignedInfo> proporciona el valor efectivo de firma y una referencia a la clave pública usada para verificar la firma (en este caso el certificado incluido en el <wsse:BinarySecurityToken> anteriormente en el encabezado, según lo identifica wsu:Id="CertId-2650016").


Cifrando y firmando mensajes

Añadir cifrado el intercambio de mensaje firmado, requiriendo solo la adición de un elemento <sp:EncryptedParts> a la política para identificar el componente(s) a ser firmados, y alguna información adicional de configuración Rampart. El Listado 4 muestra la versión del cliente de una política para este propósito (editada de nuevo para que se ajuste al ancho de página — vea el archivo signencr-policy-client.xml en el código de ejemplo para el texto completo), con las adiciones a la política del Listado 1 en negrita:

Listado 4. WS-Policy/WS-SecurityPolicy p ara firma y posterior cifrado (cliente)
<!-- Client policy for first signing and then encrypting all messages, with the
 certificate included in the message from client to server but only a thumbprint
 on messages from the server to the client. -->
<wsp:Policy wsu:Id="SignEncr"
    xmlns:wsu="http://.../oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
  <wsp:ExactlyOne>
    <wsp:All>
      <sp:AsymmetricBinding
          xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
        <wsp:Policy>
          <sp:InitiatorToken>
            <wsp:Policy>
              <sp:X509Token
                  sp:IncludeToken="http://.../IncludeToken/AlwaysToRecipient"/>
            </wsp:Policy>
          </sp:InitiatorToken>
          <sp:RecipientToken>
            <wsp:Policy>
              <sp:X509Token
                  sp:IncludeToken="http://.../IncludeToken/Never">
                <wsp:Policy>
                  <sp:RequireThumbprintReference/>
                </wsp:Policy>
              </sp:X509Token>
            </wsp:Policy>
          </sp:RecipientToken>
          <sp:AlgorithmSuite>
            <wsp:Policy>
              <sp:TripleDesRsa15/>
            </wsp:Policy>
          </sp:AlgorithmSuite>
          <sp:Layout>
            <wsp:Policy>
              <sp:Strict/>
            </wsp:Policy>
          </sp:Layout>
          <sp:IncludeTimestamp/>
          <sp:OnlySignEntireHeadersAndBody/>
        </wsp:Policy>
      </sp:AsymmetricBinding>
      <sp:SignedParts xmlns:sp="http://.../200702">
        <sp:Body/>
      </sp:SignedParts>
      <sp:EncryptedParts xmlns:sp="http://.../200702">
        <sp:Body/>
      </sp:EncryptedParts>

      <ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
        <ramp:user>clientkey</ramp:user>
        <ramp:encryptionUser>serverkey</ramp:encryptionUser>
        <ramp:passwordCallbackClass
            >com.sosnoski.ws.library.adb.PWCBHandler</ramp:passwordCallbackClass>

        <ramp:signatureCrypto>
          <ramp:crypto provider="org.apache.ws.security.components.crypto.Merlin">
            <ramp:property name="org.apache.ws.security.crypto.merlin.keystore.type"
                >JKS</ramp:property>
            <ramp:property name="org.apache.ws.security.crypto.merlin.file"
                >client.keystore</ramp:property>
            <ramp:property
                name="org.apache.ws.security.crypto.merlin.keystore.password"
                >nosecret</ramp:property>
          </ramp:crypto>
        </ramp:signatureCrypto>

        <ramp:encryptionCrypto>
          <ramp:crypto provider="org.apache.ws.security.components.crypto.Merlin">
            <ramp:property name="org.apache.ws.security.crypto.merlin.keystore.type"
                >JKS</ramp:property>
            <ramp:property name="org.apache.ws.security.crypto.merlin.file"
                >client.keystore</ramp:property>
            <ramp:property
                name="org.apache.ws.security.crypto.merlin.keystore.password"
                >nosecret</ramp:property>
          </ramp:crypto>
        </ramp:encryptionCrypto>

      </ramp:RampartConfig>

    </wsp:All>
  </wsp:ExactlyOne>
</wsp:Policy>

¿Por qué no solo cifrado?

Sería bueno proporcionar un ejemplo de uso de solo cifrado con Axis2 y Rampart, pero esta funcionalidad está descompuesta en Axis2 1.4 (y anterior). Hay una reparación de código disponible para el release 1.5. Si usted está usando Axis2 1.5 o posterior (junto con el release Rampart correspondiente), intente usar los archivos de política encr-policy-client.xml y encr-policy-server.xml para cifrar el cuerpo de cada mensaje sin usar firmas.

El primer cambio de la política del Listado 4 no es obligatorio para poder usar el cifrado , pero es una buena idea. Cuando se esté usando cifrado, el cliente necesita tener disponible el certificado de servidor cuando se envía la solicitud inicial (porque la clave pública de servidor del certificado es usada para cifrado). Como el cliente de todas formas necesita tener el certificado de servidor, nunca hay una razón para enviar el certificado de servidor al cliente. El <sp:RecipientToken> que cambió en la política del Listado 4 refleja su uso, diciendo que no se debe enviar un certificado (sp:IncludeToken=".../Never") y que un thumbprint reference (básicamente un hash del certificado) se debe usar en su lugar. La referencia thumbprint es mucho más compacta que un certificado completo, por lo que usar la referencia reduce el tamaño de mensaje y la sobrecarga de procesamiento.

El cambio que en realidad implementa el cifrado es el elemento adicionado <sp:EncryptedParts> . Este elemento informa que se usará cifrado y el elemento <sp:Body> de contenido informa que el cuerpo de mensaje SOAP es la parte del mensaje a ser cifrada.

La información de configuración Rampart añadida en el Listado 4 consiste en un elemento <ramp:encryptionUser> que proporciona el alias para la clave pública (esto es, el certificado) a ser usado para cifrar el mensaje, y un elemento <ramp:encryptionCrypto> que indica cómo acceder al almacén de claves que contiene el certificado. En la aplicación de ejemplo se utiliza el mismo almacén de claves tanto para la clave privada usada para firmar y para la clave pública usada para cifrado, así que el elemento <ramp:encryptionCrypto> es solo un duplicado renombrado del elemento <ramp:signatureCrypto> existente.

En el momento de la ejecución, Rampart necesita obtener la contraseña usada para proteger la clave privada a ser usada para descifrar los datos cifrados. El llamado de retorno de contraseña se usó anteriormente para obtener la contraseña de clave privada para inicio de sesión, mostrada en el Listado 2, también proporciona la contraseña para descifrado, así que no se necesitan cambios aquí.

Ejecutando la aplicación de ejemplo

Para probar la aplicación de ejemplo usando la firma seguida por el cifrado, usted primero necesita editar el archivo build.properties. Cambie la línea de política de cliente por client.policy=signencr-policy-client.xml y la política de servidor paraserver-policy=signencr-policy-server.xml. Luego usted puede reconstruir la aplicación ejecutando ant, implemente el archivo library-signencr.aar generado en su instalación Axis2, y ejecutar ant run para intentarlo.

El Listado 5 muestra una captura de mensaje de solicitud cuando se firma después de que se usa el cifrado, con las diferencias significativas desde la versión de solo firma del Listado 3 en negrita:

Listado 5. Mensaje usando firma y cifrado
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
  <soapenv:Header>
    <wsse:Security xmlns:wsse=".../oasis-200401-wss-wssecurity-secext-1.0.xsd"
        soapenv:mustUnderstand="1">
      <wsu:Timestamp xmlns:wsu=".../oasis-200401-wss-wssecurity-utility-1.0.xsd"
          wsu:Id="Timestamp-4067003">
        <wsu:Created>2009-04-21T23:15:47.701Z</wsu:Created>
        <wsu:Expires>2009-04-21T23:20:47.701Z</wsu:Expires>
      </wsu:Timestamp>
      <xenc:EncryptedKey Id="EncKeyId-urn:uuid:6E12E251E439C034FA12403557497352">
        <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
        <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
          <wsse:SecurityTokenReference>
            <wsse:KeyIdentifier
                EncodingType="http://...-wss-soap-message-security-1.0#Base64Binary"
                ValueType="http://.../oasis-wss-soap-message-security-1.1#ThumbprintSHA1"
                >uYn3PK2wXheN2lLZr4n2mJjoWE0=</wsse:KeyIdentifier>
          </wsse:SecurityTokenReference>
        </ds:KeyInfo>
        <xenc:CipherData>
          <xenc:CipherValue>OBUcMI...OIPQEUQaxkZps=</xenc:CipherValue>
        </xenc:CipherData>
        <xenc:ReferenceList>
          <xenc:DataReference URI="#EncDataId-28290629"/>
        </xenc:ReferenceList>
      </xenc:EncryptedKey>
      <wsse:BinarySecurityToken
          xmlns:wsu="http://.../oasis-200401-wss-wssecurity-utility-1.0.xsd"
          EncodingType="http://...-wss-soap-message-security-1.0#Base64Binary"
          ValueType="http://.../oasis-200401-wss-x509-token-profile-1.0#X509v1"
          wsu:Id="CertId-2650016">MIICo...QUBCPx+m8/0n33w==</wsse:BinarySecurityToken>
      <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
          Id="Signature-12818976">
        <ds:SignedInfo>
          <ds:CanonicalizationMethod
              Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
          <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
          <ds:Reference URI="#Id-28290629">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <ds:DigestValue>5RQy7La+tL2kyz/ae1Z8Eqw2qiI=</ds:DigestValue>
          </ds:Reference>
          <ds:Reference URI="#Timestamp-4067003">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <ds:DigestValue>GAt/gC/4mPbnKcfahUW0aWE43Y0=</ds:DigestValue>
          </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>DhamMx...+Umrnims=</ds:SignatureValue>
        <ds:KeyInfo Id="KeyId-31999426">
          <wsse:SecurityTokenReference
              xmlns:wsu=".../oasis-200401-wss-wssecurity-utility-1.0.xsd"
              wsu:Id="STRId-19267322">
            <wsse:Reference URI="#CertId-2650016"
                ValueType=".../oasis-200401-wss-x509-token-profile-1.0#X509v1"/>
          </wsse:SecurityTokenReference>
        </ds:KeyInfo>
      </ds:Signature>
    </wsse:Security>
  </soapenv:Header>
  <soapenv:Body
      xmlns:wsu=".../oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Id-28290629">
    <xenc:EncryptedData Id="EncDataId-28290629"
        Type="http://www.w3.org/2001/04/xmlenc#Content">
      <xenc:EncryptionMethod
          Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <wsse:SecurityTokenReference
            xmlns:wsse="http://.../oasis-200401-wss-wssecurity-secext-1.0.xsd">
          <wsse:Reference URI="#EncKeyId-urn:uuid:6E12E251E439C034FA12403557497352"/>
        </wsse:SecurityTokenReference>
      </ds:KeyInfo>
      <xenc:CipherData>
        <xenc:CipherValue>k9IzAEG...3jBmonCsk=</xenc:CipherValue>
      </xenc:CipherData>
    </xenc:EncryptedData>
  </soapenv:Body>
</soapenv:Envelope>

La primera diferencia es la presencia de un elemento <xenc:EncryptedKey> en el encabezado de seguridad. El contenido de este elemento proporciona una clave secreta en forma cifrada, usando la clave pública del servidor para hacer el cifrado. La segunda diferencia es el contenido efectivo del Cuerpo SOAP, el cual ha sido reemplazado por un elemento<xenc:EncryptedData> . Este elemento de datos cifrado referencia el valor <xenc:EncryptedKey> del encabezado de seguridad como la clave para el cifrado simétrico usado en el contenido del cuerpo .


Usando sus propios certificados auto-firmados

Para obtener un certificado digital oficial firmado por una autoridad de certificado reconocida usted necesita generar un par de claves pública/privada y usar la clave pública para crear una solicitud de certificado. Luego usted envía esa solicitud de certificado a su autoridad preferida y la paga. A su vez la autoridad verifica su identidad (un paso importante para la integridad de todo el proceso, aunque es uno que algunas veces sufre de lapsos vergonzosos).

En su lugar, para pruebas o uso interno usted puede generar sus propios certificados auto-firmados. El código de ejemplo para este artículo usa dos certificados auto firmados, uno para el cliente y uno para el servidor. e l almacén de claves client.keystore usado del lado del cliente contiene la clave privada y el certificado del cliente, junto con el certificado del servidor (el cual debe estar almacenado en el cliente de manera que pueda ser aceptado como válido sin el respaldo de una autoridad certificadora cuando se use para firma, y también de manera que pueda usarse directamente para cifrado). El almacén de claves server.keystore usado del lado del servidor contiene la clave privada y el certificado del servidor, junto con el certificado del cliente (de nuevo, necesario para que el certificado pueda ser aceptado como válido).

Usted puede generar sus propias claves privadas y certificados auto firmados, y sustituir sus pares de certificados de clave generados por aquellos proporcionados en la descarga. Para hacer esto usando el programa keytool incluido en el JDK, usted abre una consola y primero ingresa esta línea de comando (dividida aquí para que se ajuste al ancho de página; usted debe ingresarlo todo como una sola línea):

keytool -genkey -alias serverkey -keypass serverpass -keyalg RSA -sigalg SHA1withRSA 
   -keystore server.keystore -storepass nosecret

El comando anterior genera la clave de servidor y el certificado con alias serverkey en un nuevo almacén de claves llamado server.keystore. (Si usted tiene un server.keystore existente en este directorio, primero necesitará eliminar el par de claves existentes usando ese alias). La keytool pregunta un número de elementos de información usados para la generación del certificado (ninguno de los cuales realmente importa para uso en pruebas) y luego le pide que apruebe la información. En cuanto usted lo ha hecho escribiendo yes, keytool crea el almacén de claves con la clave privada y el certificado y luego sale.

Luego, ejecute el mismo procedimiento para crear el par de cliente y el almacén de claves, usando esta vez esta línea de comando (ingresada como una línea individual):

keytool -genkey -alias clientkey -keypass clientpass -keyalg RSA -sigalg SHA1withRSA 
   -keystore client.keystore -storepass nosecret

El siguiente paso es exportar el certificado desde el almacén de claves del servidor, e importar ese certificado en el almacén de claves del cliente. Para exportar, use esta línea de comando dividida aquí para que se ajuste al ancho de página; usted debe ingresarlo todo como una sola línea):

keytool -export -alias serverkey -keystore server.keystore -storepass nosecret 
   -file servercert.cer

La exportación crea un archivo de certificado llamado servercert.cer, el cual usted puede importar luego al almacén de claves del cliente usando esta línea de comando (ingresada como una sola línea):

keytool -import -alias serverkey -keystore client.keystore -storepass nosecret 
   -file servercert.cer

Cuando usted ejecuta el comando de importación, keytool imprime los detalles del certificado y le pregunta si usted confía en el certificado. En cuanto usted acepta la clave ingresando yes, esta añade el certificado al almacén de claves y sale.

Para el paso final, exporte el certificado del cliente e importe eso en el almacén de claves del servidor, ejecutando primero (ingresado como una sola línea):

keytool -export -alias clientkey -keystore client.keystore -storepass nosecret 
   -file clientcert.cer

Luego ejecute (dividida aquí para que se ajuste al ancho de página; usted debe ingresarlo como una sola línea):

keytool -import -alias clientkey -keystore server.keystore -storepass nosecret 
   -file clientcert.cer

¿Por qué exportar/importar ambos certificados?

El texto le pide exportar un certificado para cada parte y luego importa ese certificado en el almacén de claves para la otra parte. Usted necesitaría hacer esto para el certificado de servidor si estuviera usando cifrado, incluso si el certificado estuviera firmado por una autoridad aceptada, porque el cifrado requiere acceso a la clave pública de la otra parte. Por otro lado, para el certificado del cliente, la importación hacia el almacén de claves del servidor es necesaria solo porque el certificado es auto generado y no podría ser validado de otra forma. Al importar el certificado al almacén de claves usted está aprobándolo de antemano, por lo que la validación mediante una autoridad no es necesaria.

Usted puede usar este mismo enfoque para trabajar con múltiples clientes usando certificados auto-firmados, simplemente importando el certificado de cada cliente en el almacén de claves del servidor. Como otra alternativa, en lugar de trabajar con certificados auto-firmados, usted puede ejecutar su propia autoridad certificada (con una herramienta como OpenSSL) y requerir que cada cliente obtenga un certificado firmado por esa autoridad. De esa forma, usted puede añadir la autoridad certificada a su almacén de claves de servidor y cualquier cliente que presente un certificado firmado por esa autoridad será aceptado. O usted puede simplemente pagar para usar certificados oficiales firmados por una autoridad aceptada.

Para hacer uso de la nuevas claves y certificados usted debe copiar el archivo client.keystore en el directorio client/src del código de ejemplo antes de ejecutar la construcción de cliente (o simplemente copiarlo en el directorio client/bin para que surta efecto inmediato) y el archivo server.keystore en el directorio server/src del código de ejemplo antes de ejecutar la construcción de servidor.

Las líneas de comandos keytool de muestra en esta sección usaron los mismos nombres de archivo y contraseñas que en el código de ejemplo suministrado. Usted también puede cambiar estos valores cuando genere sus propias claves y certificados, pero luego también necesitará cambiar el código de ejemplo para que corresponda. La contraseña de almacén de claves y el nombre de archivo son parámetros en la sección RampartConfig del archivo de política de cada una de las partes. La contraseña clave de cliente tiene codificación fuerte en la versión de cliente de la clase com.sosnoski.ws.library.adb.PWCBHandler y la contraseña clave de servidor en la versión de servidor de la misma clase.


Resumiendo

En este artículo usted ha visto cómo utilizar Axis2 y Rampart para cifrado y firmas WS-Security basados en políticas. Estos poderosos recursos de seguridad son esenciales para muchos tipos de intercambios de datos de negocios, pero estos incluyen un costo en términos de sobrecarga de procesamiento. En la siguiente entrega de artículos Servicios Web Java , usted verá cómo los costos relativos de desempeño de diferentes tipos de seguridad se apilan de manera que usted puede juzgar mejor cómo usar la seguridad en sus propias aplicaciones.


Descargar

DescripciónNombretamaño
Source code for this articlej-jws5.zip36KB

Recursos

Aprender

Obtener los productos y tecnologías

  • Apache Axis2: Descargue el último release Axis2.
  • Rampart: Descargue el módulo Rampart para Axis2.
  • The Legion of the Bouncy Castle: Descargue el .jar Bouncy Castle adecuado para su tiempo de ejecución.
  • TCPMon: Descargue este recurso de fuente abierta para el monitoreo de conexiones TCP.

Comentar

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=tecnologia Java, SOA y servicios web
ArticleID=784561
ArticleTitle=Servicios Web Java: Firma y cifrado de WS-Security de Axis2
publish-date=01162012