Pregunta

Todavía no he visto muchas preguntas relacionadas con Ginebra, he publicado esta pregunta en Foro de Ginebra también ...

Estoy trabajando en un escenario en el que tenemos una aplicación de formularios ganadores con una base de instalación amplia, que emitirá llamadas frecuentes a varios servicios alojados de forma centralizada a lo largo de su operación.

Todos los servicios utilizan el Marco de Ginebra y se espera que todos los clientes llamen a nuestro STS primero para que se les emita un token para permitir el acceso a los servicios.

Fuera de la caja, usando ws2007FederationHttpBinding, la aplicación puede configurarse para recuperar un token del STS antes de cada llamada de servicio, pero obviamente esta no es la forma más eficiente, ya que casi estamos duplicando el esfuerzo de llamar a los servicios .

Alternativamente, he implementado el código requerido para recuperar el token " manualmente " desde la aplicación, y luego pase el mismo token de recuperación previa al llamar a las operaciones en los servicios (según la muestra de WSTrustClient y ayudar al foro); Eso funciona bien y, por lo tanto, tenemos una solución, pero creo que no es muy elegante, ya que requiere construir el canal WCF en código, alejándose de la maravillosa configuración de WCF.

Prefiero el enfoque ws2007FederationHttpBinding donde el cliente simplemente llama al servicio como cualquier otro servicio WCF, sin saber nada acerca de Ginebra, y los enlaces se encargan del intercambio de token.

Luego, alguien (Jon Simpson) me dio [lo que creo que es] una gran idea: agregar un servicio, alojado en la aplicación para almacenar en la memoria caché los tokens recuperados. El servicio de caché local implementaría el mismo contrato que el STS; al recibir una solicitud, verificará si existe un token de cahced y, de ser así, lo devolvería; de lo contrario, llamaría al STS "real", recuperaría un token nuevo, lo almacenaría en la memoria caché y lo devolvería. La aplicación cliente podría seguir utilizando ws2007FederationHttpBinding, pero en lugar de tener el STS como emisor tendría la memoria caché local;

De esta manera, creo que podemos lograr lo mejor de ambos mundos: el almacenamiento en caché de tokens sin el código personalizado específico del servicio; nuestro caché debe ser capaz de manejar tokens para todos los RP.

He creado un prototipo muy simple para ver si funciona y, lamentablemente, no me sorprende, estoy un poco atascado -

Mi servicio local (actualmente una aplicación de consola) recibe la solicitud y, por primera vez, llama al STS para recuperar el token, lo almacena en la memoria caché y lo devuelve al cliente que, posteriormente, lo utiliza para llamar al RP. todo funciona bien

La segunda vez, sin embargo, mi servicio de cahce local intenta usar el mismo token nuevamente, pero el lado del cliente falla con una excepción MessageSecurityException -

" El procesador de seguridad no pudo encontrar un encabezado de seguridad en el mensaje. Esto podría deberse a que el mensaje no es seguro o porque existe una falta de coincidencia de enlace entre las partes que se comunican. Esto puede ocurrir si el servicio está configurado para la seguridad y el cliente no está utilizando la seguridad. & Quot;

¿Hay algo que impida que el mismo token se use más de una vez? Lo dudo porque cuando reutilizé el token según la muestra WSTrustClient funcionó bien; ¿Qué me estoy perdiendo? es mi idea posible? una buena?

Aquí están los bits de código principal (muy básicos, en esta etapa) de la memoria caché local -

    static LocalTokenCache.STS.Trust13IssueResponse  cachedResponse = null; 
    public LocalTokenCache.STS.Trust13IssueResponse Trust13Issue(LocalTokenCache.STS.Trust13IssueRequest request) 
    { 
        if (TokenCache.cachedResponse == null) 
        { 
            Console.WriteLine("cached token not found, calling STS"); 
            //create proxy for real STS 
            STS.WSTrust13SyncClient sts = new LocalTokenCache.STS.WSTrust13SyncClient(); 
            //set credentials for sts 
            sts.ClientCredentials.UserName.UserName = "Yossi"; 
            sts.ClientCredentials.UserName.Password = "p@ssw0rd"; 
            //call issue on real sts 
            STS.RequestSecurityTokenResponseCollectionType stsResponse = sts.Trust13Issue(request.RequestSecurityToken); 
            //create result object - this is a container type for the response returned and is what we need to return; 
            TokenCache.cachedResponse = new LocalTokenCache.STS.Trust13IssueResponse(); 
            //assign sts response to return value... 
            TokenCache.cachedResponse.RequestSecurityTokenResponseCollection = stsResponse; 
        } 
        else 
        { 
        } 
        //...and reutn 
        return TokenCache.cachedResponse;
¿Fue útil?

Solución

Esto es casi vergonzoso, pero gracias a Dominick Baier en el foro, ahora no me doy cuenta de que me he perdido un punto enorme (¡sabía que no tenía sentido! ¡sinceramente! :-)) -

Un token se recupera una vez por proxy de servicio, suponiendo que no haya caducado, por lo que todo lo que tenía que hacer era reutilizar el mismo proxy, lo que planeaba hacer de todos modos, pero, de forma bastante estúpida, no lo hice en mi prototipo.

Además, encontré una muestra muy interesante en las muestras de WCF de MSDN - Proveedor de token emitido duradero , que, si lo comprendo correctamente, utiliza un comportamiento de punto final personalizado en el lado del cliente para implementar el almacenamiento en caché de token, que es muy elegante.

Seguiré considerando este enfoque ya que tenemos varios servicios y, por lo tanto, podríamos lograr una mayor eficiencia al reutilizar el mismo token entre sus proxies.

Por lo tanto, dos soluciones, más o menos de mis ojos; ¡Espero que mi estupidez ayude a alguien en algún momento!

Otros consejos

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top