Servicios Web Java: Axis2 WS - Fundamentos de seguridad

Vea cómo instalar Rampart en Axis2 e implementar el manejo de UsernameToken

Aprenda cómo añadir el módulo de seguridad Rampart a Apache Axis2 y comience a usar recursos WS-Security en sus servicios web. Dennis Sosnoski resume su serie Servicios Web Java con una mirada al uso de WS-Security y WS-SecurityPolicy en Axis2, comenzando con UsernameToken como un primer paso simple. Las siguientes columnas le llevarán más allá con WS-Security y WS-SecurityPolicy, como están implementados en Axis2 y Rampart.

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

Author photoDennis Sosnoski es un consultor y entrenador especializado en servicios web y XML basados en Java. Su experiencia en el desarrollo de software profesional abarca más de 30 años, con los últimos 10 enfocados a tecnologías XML y Java ejecutadas en el servidor. Dennis es el desarrollador principal de la infraestructura JiBX XML Data Binding de fuente abierta y de la infraestructura de servicios web JiBX/WS asociada, así como también un delegado en la infraestructura de servicio web Apache Axis2. También fue uno de los miembros de Grupo Experto para las especificaciones KAX-WS 2.0 y JAXB 2.0. El material para la serie de servicios web de Java está basado en las clases de capacitación de Dennis.



06-01-2012

La seguridad es un requisito principal de muchos tipos de servicios empresariales. También es un área de riesgo intentar implementarla por usted mismo(a), porque incluso una pequeña y oscura omisión puede conducir a serias vulnerabilidades. Estas características hacen de la estandarización de la seguridad algo deseable, permitiendo a muchos expertos contribuir al estándar y evitar las omisiones de cualquier persona. Los servicios web basados en SOAP pueden ser ampliamente soportados por WS-Security y estándares relacionados para sus necesidades de seguridad, permitiendo que la seguridad sea configurada para cada servicio según sea apropiado.

Apache Axis2 soporta estos estándares de seguridad por medio del módulo Rampart (vea Recursos). En este artículo, usted verá cómo instalar, configurar y usar Rampart con Axis2 para las funciones de seguridad básica de enviar un nombre de usuario y contraseña en una solicitud de servicio. En columnas subsiguientes de esta serie, usted aprenderá cómo usar Rampart para formas más sofisticadas de seguridad.

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 usarlas para apoyarse en sus proyectos de programación.

WS-Security

WS-Security es un estándar para añadir seguridad a intercambios de mensajes de servicios web SOAP (vea Recursos). Este utiliza un elemento de encabezado de mensaje SOAP para acoplar la información de seguridad a los mensajes, en forma de tokens que transportan diferentes tipos de reclamos (que pueden incluir nombres, identidades, claves, grupos, privilegios, capacidades, y demás), junto con cifrado e información de firma digital. WS-Security soporta múltiples formatos de tokens, múltiples dominios de confianza, múltiples formatos de firma y múltiples tecnologías de cifrado, así que en la mayoría de los casos la información de encabezado necesita incluir identificación específica de formatos y algoritmos para cada componente. La información añadida puede dar como resultado una estructura compleja para la información de encabezado, como se muestra en el Listado 1— (altamente editado) un mensaje de muestra con firma y cifrado:

Listado 1. Mensaje de muestra con firma y cifrado
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" ...>
 <soap:Header>
  <wsse:Security soap:mustUnderstand="1">
   <wsu:Timestamp wsu:Id="Timestamp-d2e3c4aa-da82-4138-973d-66b596d66b2f">
    <wsu:Created>2006-07-11T21:59:32Z</wsu:Created>
    <wsu:Expires>2006-07-12T06:19:32Z</wsu:Expires>
   </wsu:Timestamp>
   <wsse:BinarySecurityToken ValueType="...-x509-token-profile-1.0#X509v3"
     EncodingType="...-wss-soap-message-security-1.0#Base64Binary"
     xmlns:wsu="...oasis-200401-wss-wssecurity-utility-1.0.xsd"
     wsu:Id="SecurityToken-faa295...">MIIEC56MQswCQY...</wsse:BinarySecurityToken>
   <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
    <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
    <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
     <wsse:SecurityTokenReference>
      <wsse:KeyIdentifier ValueType=
       "...#X509SubjectKeyIdentifier">LlYsHyhNnOVA9Aj7...</wsse:KeyIdentifier>
     </wsse:SecurityTokenReference>
    </KeyInfo>
    <xenc:CipherData>
     <xenc:CipherValue>g+A2WJhsoGBKUydZ9Za...</xenc:CipherValue>
    </xenc:CipherData>
    <xenc:ReferenceList>
     <xenc:DataReference URI="#EncryptedContent-ba0556c3-d443-4f34-bcd1-14cbc32cd689" />
    </xenc:ReferenceList>
   </xenc:EncryptedKey>
   <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
     <ds:CanonicalizationMethod
       Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"
       xmlns:ds="http://www.w3.org/2000/09/xmldsig#" />
     <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
     <Reference URI="#Id-c80f735c-62e9-4001-8094-702a4605e429">
      <Transforms>
       <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
      </Transforms>
      <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
      <DigestValue>lKjc5nyLQDZAIu/hZb4B6mLquow=</DigestValue>
     </Reference>
     ...
    </SignedInfo>
    <SignatureValue>TiLmWvlz3mswinLVQn58BgYS0368...</SignatureValue>
    <KeyInfo>
     <wsse:SecurityTokenReference>
      <wsse:Reference URI="#SecurityToken-faa295..."
        ValueType="...-x509-token-profile-1.0#X509v3" />
     </wsse:SecurityTokenReference>
    </KeyInfo>
   </Signature>
  </wsse:Security>
 </soap:Header>
 <soap:Body wsu:Id="Id-8db9ff44-7bef-4737-8091-cdac51a34db8">
  <xenc:EncryptedData Id="EncryptedContent-ba05..."
    Type="http://www.w3.org/2001/04/xmlenc#Content"
    xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
   <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
   <xenc:CipherData>
    <xenc:CipherValue>mirmi0KuFEEI56eu2U3cICz...</xenc:CipherValue>
   </xenc:CipherData>
  </xenc:EncryptedData>
 </soap:Body>
</soap:Envelope>

En este artículo, usted verá algunos ejemplos simples de encabezados WS-Security, con un solo token. El siguiente artículo de la serie profundizará un poco más en la discusión sobre el tipo de estructura compleja mostrada en el Listado 1.

WS-Security a intercambios efectivos de mensajes SOAP. La implementación de servicio puede verificar que WS-Security ha sido aplicada adecuadamente a los mensajes entrantes, pero los clientes necesitan saber por anticipado qué deben implementar para poder usar el servicio. Con la complejidad de WS-Security y el número de opciones soportadas, puede ser difícil simplemente usar una descripción de texto para este propósito, y la configuración manual del manejo WS-Security puede causar errores. WS-Policy es una estructura de propósito general para la especificación de requisitos de extensión para servicios web, y WS-SecurityPolicy es una extensión de WS-Policy específicamente para soporte WS-Security. Juntos, estos dos estándares soportan la descripción de requerimientos WS-Security en forma legible por máquinas. La información de WS-Policy y WS-SecurityPolicy puede usarse sola o incorporada directamente a documentos Web Services Description Language (WSDL), de manera que las infraestructuras de servicios web puedan configurarse por sí mismas automáticamente para los requerimientos de un servicio.


Presentando Rampart

Rampart es el módulo de seguridad Axis2, el cual soporta WS-Security, WS-SecurityPolicy, WS-SecureConversation y WS-Trust. En este artículo, usted solo verá las funciones WS-Security y WS-SecurityPolicy de Rampart; artículos posteriores le ofrecerán una perspectiva sobre los demás recursos.

Como Rampart es implementado como un módulo (en realidad un par de módulos — rampart.mar y rahas.mar), este se acopla en la infraestructura de procesamiento Axis2 y hace su trabajo al interceptar mensajes en puntos particulares del procesamiento entrante y saliente, verificando o haciendo cambios en los mensajes según sea apropiado.

Instalando Rampart

Rampart incluye varios archivos .jar (en el directorio de biblioteca de distribución), junto con un par de archivos de módulos .mar (en el directorio de distribución). Usted debe añadir los archivos .jar a su ruta de acceso con el fin de usar Rampart con Axis2, y debe añadir los archivos .mar a su ruta de acceso o a una estructura de repositorio Axis2.

La forma más fácil de manejar los archivos Rampart .jar y .mar es añadirlos a su instalación Axis2. usted puede simplemente copiar los archivos .jar directamente del directorio de biblioteca Rampart hacia su directorio de biblioteca Axis2, y los archivos .mar desde el directorio de distribución Rampart hacia su repositorio Axis2/directorio de módulos. (También puede usar el Ant build.xml del directorio de muestras Rampart para copiar los archivos en toda su instalación Axis2. Simplemente establezca la variable de ambiente AXIS2_HOME en su directorio de instalación Axis2 y ejecute ant desde una consola abierta al directorio de muestra Rampart).

Para muchos recursos WS-Security, usted también necesita añadir el proveedor de seguridad Bouncy Castle a su configuración de seguridad JVM y el .jar Bouncy Castle a su instalación Axis2. Este paso — no es necesario para el UsernameToken sobre el cual usted aprenderá en este artículo — es requerido para otros recursos de seguridad que cubriremos más adelante en la serie. Por motivos de patentes con algunos de los algoritmos de seguridad, el Bouncy Castle .jar es una descarga separada de Rampart (vea Recursos). Descargue la versión apropiada del .jar para su tiempo de ejecución Java, y el .jar al directorio de biblioteca Axis2. Luego necesitará modificar las políticas de seguridad de su instalación Java para usar el código Bouncy Castle, añadiendo una línea a su archivo java.security que se encuentra en si biblioteca de tiempo de ejecución Java/directorio de seguridad. Busque la sección del archivo con varias líneas security.provider diferentes y añada la siguiente línea:

security.provider.99=org.bouncycastle.jce.provider.BouncyCastleProvider

El orden de las líneas security.provider en el archivo no importa, pero es una buena idea añadir esto después de las otras líneas para implementaciones predefinidas de proveedor de seguridad.

Para usar el código Rampart en una instalación de servidor Axis2 usted necesita crear un nuevo archivo axis2.war, uno que incluya los archivos Rampart .jar y .mar añadidos. Usted puede usar el Ant build.xml proporcionado en el directorio webapp para crear axis2.war, siempre y cuando usted haga un cambio: elimine la línea <exclude name="axis2-codegen*.jar"/> que está cerca al final del archivo. Luego abra una consola hacia el directorio Axis2 webapp y ejecute ant. Después de que build.xml se ejecute, usted puede encontrar la aplicación web axis2.war creada en el directorio de distribución de instalación Axis2.


Una aplicación de muestra

La aplicación proporcionada en el código de muestra (vea Descargas) se basa en una que utilicé en "Axis2 Data Binding" para demostrar alternativas de enlace de datos para Axis2. Para este artículo y los siguientes sobre soporte de Axis2 WS-Security, lo he orientado a solo tres operaciones: getBook, addBook y getBooksByType. Para simplificar, solo se suministra la versión Axis Data Binding (ADB) del código, pero esto no es un requisito para trabajar con WS-Security en Axis2 — Rampart implementa WS-Security a un nivel que es independiente de la técnica de enlace de datos que utiliza su código, de manera que trabaja con todas las formas de enlace de datos soportadas por Axis2.

El directorio raíz del código de ejemplo es jws04code. Dentro de este directorio, usted encontrará archivos Ant build.xml y build.properties, donde el archivo library.wsdl proporciona la definición de servicio para la aplicación de ejemplo, un archivo de propiedades log4j.properties usado para configurar registros del lado del cliente, y varios archivos XML de definición de propiedades (todos llamados XXX-policy-client.xml o XXX-policy-server.xml). El archivo build.properties configura el funcionamiento de la aplicación de ejemplo. El Listado 2 muestra la versión suministrada de este archivo de propiedades:

Listado 2. Archivo build.properties suministrado
# set axis-home to your Axis2 installation directory
axis-home=PATH_TO_AXIS2_INSTALLATION
# set the connection protocol to be used to access services (http or https)
protocol=http
# set the name of the service host
host-name=localhost
# set the port for accessing the services (change this for monitoring)
host-port=8080
# set the base path for accessing all services on the host
base-path=/axis2/services/
# set the name of the policy file to be used by the client
client-policy=plain-policy-client.xml
# set the name of the policy file to be used by the server
server-policy=plain-policy-server.xml

Antes de ensayar los ejemplos, usted necesita editar el archivo build.properties y configurar la ruta efectiva hacia su instalación Axis2 (con Rampart añadido, como se trató en la sección precedente). Si usted está usando un host diferente o un número de puerto para su servidor, es posible que también necesite modificar los valores host-name y host-port . Hablaré sobre los valores restantes más adelante en este artículo.


Dando una oportunidad a WS-Security

WS-Security define varios tipos de tokens de seguridad (incluyendo tokens que son parte de la especificación principal, y aquellos definidos por perfiles como extensiones de plug-in a la especificación), con muchas opciones en cuanto a cómo se construyen y se usan los tokens. El objetivo de este artículo es la configuración y el uso de Rampart con Axis2, así que solo usaré el token útil más simple como ejemplo: el UsernameToken, definido por el perfil UsernameToken .

UsernameToken WS-SecurityPolicy

El propósito de un UsernameToken es simplemente transportar información de nombre de usuario y de contraseña como parte de los encabezados de WS-Security. La forma más básica de UsernameToken envía tanto el nombre de usuario como la contraseña como texto plano. Esto no es lo óptimo desde el punto de vista de la seguridad (aunque no hay nada malo en usar este enfoque sobre conexiones seguras), pero es fácil ver lo que se está enviando, haciendo de ello un punto de partida útil.

La configuración WS-SecurityPolicy para un UsernameToken enviado como texto puede ser tan simple como se muestra en el Listado 3. Esta política (mostrada aquí con una línea dividida en dos para que se ajuste al ancho de página — no válido para el uso real) consiste en un empaquetador WS-Policy estándar (los elementos que usan el prefijo wsp ) en torno a una afirmación UsernameToken de WS-SecurityPolicy.

Listado 3. WS-SecurityPolicy para texto plano UsernameToken
<wsp:Policy wsu:Id="UsernameToken" xmlns:wsu=
    "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
  <wsp:ExactlyOne>
    <wsp:All>
      <sp:SupportingTokens
          xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
        <wsp:Policy>
          <sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/
               ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"/>
        </wsp:Policy>
      </sp:SupportingTokens>
    </wsp:All>
  </wsp:ExactlyOne>
</wsp:Policy>

El UsernameToken en el Listado 3 usa un atributo IncludeToken para especificar el tipo de flujo de mensaje que va a incluir el token — en este caso, todos los flujos de mensaje que van desde el iniciador de una solicitud (este es, el cliente) hacia el receptor de la solicitud (el servidor). Usted puede usar otros valores definidos para el atributo IncludeToken para especificar otros usos del token, pero para unUsernameToken este generalmente es el único valor que tiene sentido.

Aplicando la política

WS-Policy y WS-SecurityPolicy están diseñados para soportar integración dentro de definiciones de servicio WSDL. Se utilizan referencias para asociar una política a una o más definiciones<wsdl:binding>, <wsdl:binding>/<wsdl:operation> o <wsdl:message> . Axis2 1.4.X implementa manejo preliminar para políticas incorporadas en WSDL, pero para Axis2 1.4.1 la implementación todavía no es sólida. En su lugar, este artículo acopla las políticas directamente al cliente y al servidor con el fin de ser compatible con el código 1.4.1.

Manejo de políticas del lado del servidor

Para el lado del servidor, usted aplica una política añadiéndola al archivo de configuración services.xml incluido en cada archivo de servicio Axis2 .aar. La política se puede añadir directamente como hija de un elemento <service> para que aplique a todas las operaciones definidas por ese servicio. Usted también necesita añadir un elemento <module> a services.xml para decirle a Axis2 que el módulo Rampart debe estar incluido en la configuración para el servicio. El Listado 4 es una versión editada de services.xml usada por la aplicación de ejemplo, con la referencia de módulo y la información de política mostradas en negrita:

Listado 4. services.xml con política incorporada
<serviceGroup>
  <service name="library-username">
    <messageReceivers>
      <messageReceiver
          class="com.sosnoski.ws.library.adb.LibraryUsernameMessageReceiverInOut"
          mep="http://www.w3.org/ns/wsdl/in-out"/>
    </messageReceivers>
    <parameter
        name="ServiceClass">com.sosnoski.ws.library.adb.LibraryUsernameImpl</parameter>
    <parameter name="useOriginalwsdl">true</parameter>
    <parameter name="modifyUserWSDLPortAddress">true</parameter>
    <operation mep="http://www.w3.org/ns/wsdl/in-out" name="getBook"
        namespace="http://ws.sosnoski.com/library/wsdl">
      <actionMapping>urn:getBook</actionMapping>
      <outputActionMapping>http://.../getBookResponse</outputActionMapping>
    </operation>
    ...

    <module ref="rampart"/>
    <wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
        xmlns:wsu="http://.../oasis-200401-wss-wssecurity-utility-1.0.xsd"
        wsu:Id="UsernameToken">
      <wsp:ExactlyOne>
        <wsp:All>
          <sp:SupportingTokens
              xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
            <wsp:Policy>
              <sp:UsernameToken
                  sp:IncludeToken="http://.../IncludeToken/AlwaysToRecipient">
                <wsp:Policy>
                  <sp:HashPassword/>
                </wsp:Policy>
              </sp:UsernameToken>
            </wsp:Policy>
          </sp:SupportingTokens>

          <ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
            <ramp:passwordCallbackClass>...PWCBHandler</ramp:passwordCallbackClass>
          </ramp:RampartConfig>

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

Regenerando services.xml de la forma fácil

Cuando usted usa la herramienta Axis2 Wsdl2Java para generar archivos de implementación del lado del servidor, esta crea un archivo services.xml como parte de los artefactos generados (en el directorio de recursos, bajo su directorio objetivo de generación). Cada vez que la definición de su servicio WSDL cambie, usted debe regenerar este archivo, por lo cual la necesidad de incorporar referencia de módulo e información de política en el archivo puede ser algo molesto. El código de ejemplo incluye una herramienta para automatizar esta modificación al archivo generado: la clase com.sosnoski.ws.MergeServerPolicy . (Fuente y binario están en el directorio mergetool). El generate-server del archivo build.xml objetivo ejecuta esta herramienta para insertar la referencia de módulo y la información de política apropiada, dentro del archivo services.xml generado cada vez que se genera el código de servidor. Usted puede usar la herramienta para sus propios proyectos si lo desea. Esta toma la ruta hacia el archivo services.xml como el primer parámetro de línea de comandos, la ruta hacia el archivo de política como el segundo, y los nombres de cualquier módulo a ser añadido como los parámetros de línea de comandos restantes.

Si usted compara la política incorporada en el Listado 4 con la política básica del Listado 3, podrá ver una adición — un elemento <ramp:RampartConfig> . Este elemento proporciona extensiones Rampart específicas para la información de política, dando en este caso el nombre de una clase a ser usada para el manejo de llamadas de retorno de contraseña. La llamada de retorno es la forma en que su código de servidor puede verificar la combinación de nombre de usuario y contraseña suministrada por el cliente tras solicitud.

El Listado 5 muestra la implementación efectiva de la clase de llamado de retorno, como se usa para la contraseña de texto plano. En este caso, tanto el nombre de usuario como la contraseña son suministrados al llamado de retorno, y todo lo que necesita hacer el llamado de retorno es verificar la combinación. Si el nombre de usuario y la contraseña coinciden con los valores esperados, esto simplemente retorna; en caso contrario, arroja una excepción para indicar el error.

Listado 5. Código de llamado de retorno de contraseña
import org.apache.ws.security.WSPasswordCallback;

public class PWCBHandler implements CallbackHandler
{
    public void handle(Callback[] callbacks)
        throws IOException, UnsupportedCallbackException {
        for (int i = 0; i < callbacks.length; i++) {
            WSPasswordCallback pwcb = (WSPasswordCallback)callbacks[i];
            String id = pwcb.getIdentifer();
            if (pwcb.getUsage() == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN) {

                // used when plain-text password in message
                if (!"libuser".equals(id) || !"books".equals(pwcb.getPassword())) {
                    throw new UnsupportedCallbackException(callbacks[i], "check failed");
                }

            }
        }
    }
}

Para una aplicación real, naturalmente usted deseará usar algún otro mecanismo (como una base de datos o un mecanismo de seguridad externo) para verificar la combinación de nombre de usuario y contraseña. La técnica de llamada de retorno le permite usar cualquier técnica de verificación que desee, como una extensión del manejo de seguridad Rampart.

Configuración del lado del cliente

Para usar Rampart para su código de cliente, usted primero necesita tener el módulo disponible para uso con Axis2. Usted puede hacer esto configurando una estructura de repositorio Axis2 para el cliente, pero es generalmente más fácil simplemente incluir el archivo de módulo rampart.mar (y cualquier otro módulo que usted necesite usar) en su ruta de acceso de clase. El ejemplo proporcionado usa el enfoque de ruta de acceso de clase.

Luego usted necesitará configurar la política de seguridad y los parámetros relacionados para el cliente. La forma más fácil de manejar esta configuración es establecer valores directamente en el talón de servicio. El Listado 6 muestra cómo se hace la configuración en el código de ejemplo:

Listado 6. Configuración de cliente
    /**
     * Load policy file from classpath.
     */
    private static Policy loadPolicy(String name) throws XMLStreamException {
        ClassLoader loader = WebServiceClient.class.getClassLoader();
        InputStream resource = loader.getResourceAsStream(name);
        StAXOMBuilder builder = new StAXOMBuilder(resource);
        return PolicyEngine.getPolicy(builder.getDocumentElement());
    }

    public static void main(String[] args) throws IOException, XMLStreamException {

        // check for required command line parameters
        if (args.length < 4) {
            System.out.println("Usage:\n  java " +
                "com.sosnoski.ws.library.adb.WebServiceClient protocol host port path");
            System.exit(1);
        }

        // create the client stub
        String target = args[0] + "://" + args[1] + ":" + args[2] + args[3];
        System.out.println("Connecting to " + target);
        LibraryUsernameStub stub = new LibraryUsernameStub(target);

        // configure and engage Rampart
        ServiceClient client = stub._getServiceClient();
        Options options = client.getOptions();
        options.setProperty(RampartMessageData.KEY_RAMPART_POLICY,
            loadPolicy("policy.xml"));
        options.setUserName("libuser");
        options.setPassword("books");
        client.engageModule("rampart");

La porción de configuración es el bloque de código final en el Listado 6. Este obtiene la instancia org.apache.axis2.client.ServiceClient del talón creado y establece la información de política (cargada de la ruta de acceso de clase) y el nombre de usuario/contraseña en las opciones de cliente. Luego activa el módulo Rampart en la configuración Axis2 usada por el cliente. En cuanto esto se ha hecho, usted puede usar el talón para acceder al servicio tal como lo haría sin WS-Security, y Rampart añade el UsernameToken automáticamente a cada solicitud.

Confirmando los resultados

Con Ant instalado, usted simplemente puede ejecutar ant desde una consola abierta al directorio de código de ejemplo, para crear código tanto de cliente como de servidor. Luego usted puede implementar el archivos library-username.aar creado en su instalación de servidor Axis2 (una que incluya los .jars y .mars de Rampart, por supuesto), e intentar el cliente ingresando ant run en la consola. Si todo está configurado correctamente, usted podrá ver el resultado mostrado en la Figura 1:

Figura 1. Resultado de la consola cuando se está ejecutando la aplicación
Resultado de la consola cuando se está ejecutando la aplicación

Desde luego, solo ejecutar el cliente con el servidor no le muestra lo que está sucediendo. Usted puede usar una herramienta como TCPMon para que actúe como intermediaria entre el cliente y el servidor, y para que capture el intercambio de mensaje para ver el UsernameToken de WS-Security en acción(vea Recursos). Para hacer esto, usted primero necesita configurar TCPMon y que acepte conexiones del cliente en un puerto, el cual luego las reenvía hacia el servidor que se está ejecutando en un puerto diferente (o en un host diferente). Luego usted puede editar el archivo build.properties y cambiar el valor del host-port al puerto de escucha para TCPMon. Si usted ingresa de nuevo ant run en la consola, entonces verá los mensajes que se están intercambiando. El Listado 7 muestra una captura de muestra de mensaje del cliente:

Listado 7. Mensaje de cliente con UsernameToken
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header>
    <wsse:Security xmlns:wsse="...wss-wssecurity-secext-1.0.xsd"
        soapenv:mustUnderstand="1">
      <wsse:UsernameToken xmlns:wsu="...wss-wssecurity-utility-1.0.xsd"
          wsu:Id="UsernameToken-1815911473">
        <wsse:Username>libuser</wsse:Username>
        <wsse:Password Type="...wss-username-token-profile-1.0#PasswordText"
            >books</wsse:Password>
      </wsse:UsernameToken>
    </wsse:Security>
  </soapenv:Header>
  <soapenv:Body>
    <ns2:getBooksByType xmlns:ns2="http://ws.sosnoski.com/library/wsdl">
      <ns2:type>scifi</ns2:type>
    </ns2:getBooksByType>
  </soapenv:Body>
</soapenv:Envelope>

Asegurando UsernameToken

Un texto plano básico UsernameToken no proporciona mucha seguridad directamente, porque tanto el nombre de usuario como la contraseña correspondiente son visibles para cualquiera que pueda monitorear un mensaje. Si usted utiliza un canal de comunicación cifrado, esto no es un problema — siempre y cuando el cifrado de canal sea sólido y ningún ente externo pueda monitorear los mensajes. WS-SecurityPolicy define de forma conveniente una forma para requerir el uso de un canal cifrado, como se muestra en el Listado 8 (de nuevo, con una línea dividida para ajustarse al ancho de página — vea en el archivo secure-policy-server.xml del paquete de código de muestra la política real):

Listado 8. Política que requiere conexión HTTPS
<wsp:Policy wsu:Id="UsernameToken" xmlns:wsu=
  "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
  xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
 <wsp:ExactlyOne>
  <wsp:All>
   <sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
     <wsp:Policy>
      <sp:TransportToken>
        <wsp:Policy>
         <sp:HttpsToken RequireClientCertificate="false"/>
        </wsp:Policy>
      </sp:TransportToken>
     </wsp:Policy>
   </sp:TransportBinding>
   <sp:SupportingTokens
     xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
    <wsp:Policy>
     <sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/
          ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"/>
    </wsp:Policy>
   </sp:SupportingTokens>
  </wsp:All>
 </wsp:ExactlyOne>
</wsp:Policy>

La parte del Listado 8 mostrada en negrita es la parte añadida, que consiste en un elemento <sp:TransportBinding> y un elemento <sp:HttpsToken> anidado. El elemento <sp:HttpsToken> dice que se debe usar una conexión HTTPS segura al comunicarse con el servicio. Si usted intenta construir el .aar de servicio con esta política (cambiando el valor server-policy en build.properties por secure-policy-server.xml, y luego ejecutando ant build-server) e implementarlo, podrá ver que Rampart impone este requisito de política, rechazando cualquier conexión HTTP normal.

Si usted desea intentar una conexión HTTPS con el servicio puede hacerlo, pero primero necesitará configurar su servidor web para que soporte HTTPS. (Tomcat tiene buenas instrucciones para hacer esto, en /tomcat-docs/ssl-howto.html.) Usted también necesita cambiar el valor deprotocol en build.properties por https, y si está usando un certificado auto-firmado para el servidor web, necesitará pasar un almacén de confianza al cliente cuando esté ejecutando el Ant test objetivo. El build.xml suministrado tiene una línea comentada para hacer esto, de manera que usted puede simplemente quitar el comentario de la línea y establecer la ubicación del archivo de almacenamiento confiable apropiado en su sistema.

Otra forma de hacer al UsernameToken más seguro funciona incluso sobre enlaces no cifrados. Este método usa un valor digest computado sobre una cadena de caracteres compuesta por hasta otros dos valores de texto combinados con la contraseña. Uno de los valores de texto, el nonce, es un valor aleatorio generado por el remitente para cada solicitud. El otro, la marca de tiempo creada, es simplemente la hora en la que el remitente creó el UsernameToken. Estos dos valores está incluidos en el UsernameToken como texto plano. Cuando son usados de forma adecuada tanto por el cliente como por el servidor, la combinación de estos valores con la contraseña en el resumen hace posible que cada servidor verifique que se haya usado la contraseña correcta cuando se generó el resumen, mientras dificulta que cualquier entidad externa finja una contraseña válida. El Listado 9 proporciona una política de ejemplo para el uso del resumen, seguida por una captura efectiva de un mensaje usando la contraseña de resumen (ambos reformateados para ajustarse al ancho de página — vea el archivo hash-policy-client.xml para ver la política real). Las diferencias entre la política original de nuevo se muestran en negrita.

Listado 9. Uso de política usando resumen de contraseña y mensaje de muestra
<wsp:Policy wsu:Id="UsernameToken" xmlns:wsu=
    "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
  <wsp:ExactlyOne>
    <wsp:All>
      <sp:SupportingTokens
          xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
        <wsp:Policy>
          <sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/
ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
            <wsp:Policy>
              <sp:HashPassword/>
            </wsp:Policy>
          </sp:UsernameToken>
        </wsp:Policy>
      </sp:SupportingTokens>
    </wsp:All>
  </wsp:ExactlyOne>
</wsp:Policy>

<?xml version='1.0' encoding='UTF-8'?>
<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">
      <wsse:UsernameToken xmlns:wsu="...wss-wssecurity-utility-1.0.xsd"
          wsu:Id="UsernameToken-1421876889">
        <wsse:Username>libuser</wsse:Username>
        <wsse:Password Type="...wss-username-token-profile-1.0#PasswordDigest"
          >/Wt/2yDdZwa8a5qd7U70hrp29/w=</wsse:Password>
        <wsse:Nonce>4ZQz5ytME/RXfChuKJ03iA==</wsse:Nonce>
        <wsu:Created>2009-03-17T11:20:57.467Z</wsu:Created>
      </wsse:UsernameToken>
    </wsse:Security>
  </soapenv:Header>
  <soapenv:Body>
    <ns2:getBooksByType xmlns:ns2="http://ws.sosnoski.com/library/wsdl">
      <ns2:type>scifi</ns2:type>
    </ns2:getBooksByType>
  </soapenv:Body>
</soapenv:Envelope>

Resumiendo

En este artículo usted ha visto como usar Axis2 y Rampart para una forma básica de manejo de WS-Security basada en políticas. En la siguiente entrega de Servicios Web Java , usted aprenderá sobre dos potentes recursos de WS-Security: cifrado XML y firmas. El uso del cifrado XML le permite mantener en secreto el contenido de sus mensajes cuando está operando sobre cualquier tipo de conexión, incluso cuando participan intermediarios no confiables en el procesamiento. El uso de XML firmas le proporciona garantías de que los mensajes realmente son de quien dice estarlos originando y que el contenido del mensaje no ha sido adulterado durante el tránsito. El cifrado y las firmas son la base de la mayoría de implementaciones de seguridad corporativa, así que revise para conocer cómo puede usted aplicar estos recursos en sus propios servicios web.


Descargar

DescripciónNombretamaño
Source code for this articlej-jws4.zip10KB

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=783714
ArticleTitle=Servicios Web Java: Axis2 WS - Fundamentos de seguridad
publish-date=01062012