Uno de los problemas que tienen los servicios web es sin duda su excesiva complejidad. Pero los web services no son realmente un estándar, más bien es un conjunto de estándares que abordan los propios mensajes, el formato SOAP, el contrato, el WSDL, los registros de servicios UDDI, y también la seguridad en los mensajes.
Seguridad con WS-Security
Uno de los estándares más importantes es el que se trata la seguridad en los servicios web, el WS-Security. ¿Para qué sirve?
Básicamente para tres cosas:
- Para firmar mensajes para asegurar su origen y su integridad.
Igual que sabemos quién ha firmado contrato mirando la firma manuscrita, podemos saber en este caso quien envía una petición a un servicio web o de quién es la respuesta con WS-Signature.
También sirve para asegurarnos de que alguien ha modificado el mensaje. Que si dice que depositemos 100€ en una cuenta de la islas caimán, no venga alguien y diga que son 1.000.000 de €. Si alguien modifica el mensaje por el camino, lo sabremos. - Para encriptar el mensaje y asegurarnos de que nadie puede leer el contenido con XML-Encryption
- Asegurarnos de la identidad del que envía el mensaje
¿y que pinta tiene todo esto?
Aquí tenéis un ejemplo sacado de esta estupenda guía. Como veis, para un humano es difícil de leer aunque para una aplicación es bastante más sencillo. Sobre todo si lo comparamos con las alternativas que teníamos antes de estos estándares:
<?xml version="1.0" encoding="utf-8"?> <S:Envelope xmlns:S="http://www.w3.org/2001/12/soap-envelope" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> <S:Header> <m:path xmlns:m="http://schemas.xmlsoap.org/rp/"> <m:action>http://fabrikam123.com/getQuote</m:action> <m:to>http://fabrikam123.com/stocks</m:to> <m:from>mailto:johnsmith@fabrikam123.com</m:from> <m:id>uuid:84b9f5d0-33fb-4a81-b02b-5b760641c1d6</m:id> </m:path> <wsse:Security> <wsse:BinarySecurityToken ValueType="wsse:X509v3" Id="X509Token" EncodingType="wsse:Base64Binary"> MIIEZzCCA9CgAwIBAgIQEmtJZc0rqrKh5i... </wsse:BinarySecurityToken> <xenc:EncryptedKey> <xenc:EncryptionMethod Algorithm= "http://www.w3.org/2001/04/xmlenc#rsa-1_5"/> <ds:KeyInfo> <ds:KeyName>CN=Hiroshi Maruyama, C=JP</ds:KeyName> </ds:KeyInfo> <xenc:CipherData> <xenc:CipherValue>d2FpbmdvbGRfE0lm4byV0... </xenc:CipherValue> </xenc:CipherData> <xenc:ReferenceList> <xenc:DataReference URI="#enc1"/> </xenc:ReferenceList> </xenc:EncryptedKey> <ds:Signature> <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> <ds:Transforms> <ds:Transform Algorithm="http://...#RoutingTransform"/> <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>LyLsF094hPi4wPU... </ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue> Hp1ZkmFZ/2kQLXDJbchm5gK... </ds:SignatureValue> <ds:KeyInfo> <wsse:SecurityTokenReference> <wsse:Reference URI="#X509Token"/> </wsse:SecurityTokenReference> </ds:KeyInfo> </ds:Signature> </wsse:Security> </S:Header> <S:Body> <xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" Id="enc1"> <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#3des-cbc"/> <xenc:CipherData> <xenc:CipherValue>d2FpbmdvbGRfE0lm4byV0... </xenc:CipherValue> </xenc:CipherData> </xenc:EncryptedData> </S:Body> </S:Envelope>
17/02/2012 at 12:14
Una firma manuscrita falsificada, tiene mecanismos periciales de control de la realizacion de la misma. Pero la utilización por un tercero no autorizado de la firma digital de un sujeto particular, ¿no obliga al estafado a demostrar que él no fue quien, ese día, en ese momento concreto, no era quien usaba esa firma digital?
Se gana agilidad en el tráfico economico, pero me planteo si no es más sencillo «robar» una firma digital, que falsificar una firma manuscrita… no se…
Saludos Andrés 🙂 y gran trabajo.
17/02/2012 at 12:22
El uso de las firmas se basa en el par clave pública, clave privada. Por supuesto, la seguridad de todo esto se basa en que la clave privada no la conoce nadie salvo tú.
Ademas, para garantizar el no repudio, se suele contar con un tercero de confianza, que a modo de notario de fe de que la transacción se ha llevado a cabo por las dos partes y que ninguna de ellas pueda después negarlo.
No es un tema fácil, pero si se hace bien creo que cumple con lo que se necesita. ¿Le ves algún fallo además de lo engorroso de su uso?
Saludos y muchas gracias por tu aportación.
12/08/2015 at 04:00
Este tema de seguridad a nivel de servicios es bien interesante, ya que por ejemplo en nuestro caso lo hemos aplicados cuando requerimos la comunicación de un servicio (en su flujo), con un servicio externo al nuestro inventario (dominio/empresa), en estos casos al exponer o al consumir requerimos aplicar de alguna manera seguridad en la comunicación entre ambas partes. En este punto existen varias formas como por ejemplo:
1. Utilizar en la interface de entrada del servicio compuesto (WS) dos campos: ‘usuario’, ‘password’ (con criptografía), y cada vez que se consuma se deba de enviar la autenticación respectiva que se validará antes de proseguir el flujo.
2. Utilizar el conocido WS-Security en aplicar la configuración tanto en el servidor (webservice), para que soporte el envio de la autenticación: ‘usuario/password (con criptografía)’ viajando en la cabecera del Request respectivamente. El cliente proxy así mismo deberá setear en la cabecera del request también dichos campos.
3. Utilizar el protocolo HTTPs (SSL), habilitando el puerto y el registro del usuario/pasword requerido en el servidor de aplicación. Así mismo, el consumo de dicho WebService desde el cliente requerirá el registro en los ambiente de consumo del certificado digital por medio de los ‘KeyStore’ que vienen dentro del JDK, así mismo como la generación del Topdown en base al WSDL (el desplegado con el HTTPs y UsernameToken).
Estas tres opciones son las hemos manejado en diferentes escenarios y creo que son las más conocidas, quisiera su opinión sobre como hemos venido manejando y cual cree ud. que es la mejor de todas las utilizadas. (lo positivo & negativo). Gracias.
Saludos.
12/08/2015 at 10:03
Yo distinguiría dos aspectos, el mecanismo de autenticación y el usuario que se utiliza para autenticar.
Sobre el primer aspecto, como comentas, lo más sencillo es la seguridad BASIC que va en las credenciales del HTTP. Esto tiene como desventaja que sólo se securiza entre dos extremos de la comunicación, es decir, si el mensaje pasa por varios servidores no se mantienen estas credenciales. Para mantenerlas habría que usar WS-Security porque las credenciales van en el propio mensaje en lugar del protocolo de transporte.
Ahora bien, en la práctica, creo que en la mayoría de las ocasiones es suficiente con la seguridad BASIC. Además, se acostumbra también a que cuando la petición llega a al servidor se cambian las credenciales que vienen por otras internas.
Esto me lleva al segundo punto, en general, por motivos de sencillez es mejor (creo yo) utilizar un usuario de aplicación o genérico, en lugar de un usuario nominal. El usuario nominal da ventajas respecto a la auditoría y trazas pero es un auténtico lío configurar todo para que ese usuario tenga privilegios para accedera a todos los servicios que necesita.
En este post hablo precisamente de esto: http://pensandoensoa.com/2011/06/27/integracion-sistemas-heterogeneos-soa/
Saludos