Tenemos un servicio que maneja la autorización basada en un nombre de usuario y contraseña. En lugar de hacer que el nombre de usuario y la contraseña sean parte de la llamada, la colocamos en el encabezado SOAP.¿Cuáles son los posibles problemas con este esquema de seguridad de WebService?
En un escenario típico, un servicio web llama al servicio de autorización al inicio de la ejecución para verificar que la persona que llama puede llamarlo. Sin embargo, el problema es que algunos de estos servicios web se llaman entre sí, y eso significa que en cada subllamada se verifican los permisos del usuario, y eso puede ser muy costoso.
Lo que pensé hacer era hacer que el servicio de autorización devolviera un token de seguridad después de la primera llamada. Luego, en lugar de tener que llamar al servicio de autorización cada vez, el servicio web puede validar el encabezado de seguridad localmente.
La cabecera de seguridad se ve algo como esto (código C# - recortada para ilustrar el concepto esencial):
public sealed class SecurityHeader : SoapHeader
{
public string UserId; // Encrypted
public string Password; // Encrypted; Just realized this field isn't necessary [thanks CJP]
public DateTime TimeStamp; // Used for calculating header Expiry
public string SecurityToken;
}
La idea general es que el SecurityHeader se comprueba con cada llamada. Si existe, no ha expirado, y SecurityToken es válido, entonces el Método web procede normalmente. De lo contrario, devolverá un error o intentará volver a autorizar y generar un nuevo SecurityHeader
El SecurityToken se basa en un hash salado de UserId, Password y TimeStamp. La sal se cambia todos los días para evitar repeticiones.
El único problema que veo es que un usuario puede tener permiso para acceder al servicio web A, pero no al servicio web B. Si llama a A y recibe un token de seguridad, tal como está ahora significa que B le permitirá a través de si él usa esa misma ficha. Tengo que cambiarlo para que el token de seguridad solo sea válido desde el servicio web al servicio web, en lugar del servicio de usuario a web, es decir. Debería estar bien si el usuario llama a A que llama a B, pero no está OK si el usuario llama al Servicio A y luego al Servicio D. Una forma de evitarlo es asignar una clave común (o un conjunto de claves) a servicios lógicamente relacionados. (es decir, si el cliente puede hacer A entonces lógicamente también puede hacer B).
Como alternativa, tendría que codificar el conjunto de permisos completo del usuario como parte del encabezado de seguridad. Tendré que investigar cuál será la sobrecarga.
Editar:
Varias personas han mencionado mirar otros sistemas de seguridad como WS-Security y SAML etc que ya tengo. De hecho, recibí la idea de WS-Security. El problema es que otros esquemas no proporcionan la funcionalidad que necesito (almacenamiento en caché de información de autorización y protección contra repeticiones sin una base de datos intermedia). Si alguien sabe de un plan que sí lo haga, lo usaré en lugar de glady. Además, esto es no acerca de la autenticación. Eso es manejado por otro mecanismo más allá de mi control.
Si resulta que no hay forma de almacenar en caché los datos de autorización, significa que tendré que incurrir en la sobrecarga de la autorización en cada nivel.
Una aserción de SAML tiene el siguiente aspecto: "El cliente X tiene las funciones A y B. Esta afirmación es válida en el tiempo T. Firmado, servicio de autenticación." ¿Cómo es esto no lo que necesita? – ykaganovich
Volveré a visitar SAML y XACML hoy. – ilitirit