Domanda

Non ho ancora visto molte domande relative a Ginevra, ho pubblicato questa domanda in Forum di Ginevra pure ...

Sto lavorando a uno scenario in cui abbiamo un'app di moduli vincenti con un'ampia base di installazione, che invierà chiamate frequenti a vari servizi da noi ospitati centralmente durante il suo funzionamento.

I servizi utilizzano tutti il ??Framework di Ginevra e tutti i clienti devono chiamare prima il nostro STS per ricevere un token per consentire l'accesso ai servizi.

Immediatamente, usando ws2007FederationHttpBinding, l'app può essere configurata per recuperare un token dallo STS prima di ogni chiamata di servizio, ma ovviamente questo non è il modo più efficiente in quanto stiamo quasi duplicando lo sforzo di chiamare i servizi .

In alternativa, ho implementato il codice richiesto per recuperare il token "manualmente" dall'app e quindi passare lo stesso token pre-recuperato quando si chiamano operazioni sui servizi (basato sull'esempio WSTrustClient e aiuto sul forum); funziona bene e quindi abbiamo una soluzione, ma credo che non sia molto elegante in quanto richiede la costruzione del canale WCF in codice, allontanandosi dalla meravigliosa configurazione WCF.

Preferisco di gran lunga l'approccio ws2007FederationHttpBinding in cui il cliente chiama semplicemente il servizio come qualsiasi altro servizio WCF, senza sapere nulla di Ginevra, e le associazioni si occupano dello scambio di token.

Quindi qualcuno (Jon Simpson) mi ha dato [quello che penso sia] un'ottima idea: aggiungere un servizio, ospitato nell'app stessa per memorizzare nella cache i token recuperati localmente. Il servizio cache locale implementerebbe lo stesso contratto dell'STS; quando riceve una richiesta verificherebbe se esiste un token cahced e, in tal caso, lo restituirebbe, altrimenti chiamerebbe il "vero" STS, ritirerebbe un nuovo token, lo memorizzerà nella cache e lo restituirà. L'app client potrebbe quindi utilizzare ancora ws2007FederationHttpBinding, ma invece di avere STS come emittente avrebbe la cache locale;

In questo modo penso che possiamo ottenere il meglio da entrambi i mondi - memorizzazione nella cache dei token senza il codice personalizzato specifico del servizio; la nostra cache dovrebbe essere in grado di gestire i token per tutti gli RP.

Ho creato un prototipo molto semplice per vedere se funziona, e - un po 'non sorprendentemente purtroppo - Sono leggermente bloccato -

Il mio servizio locale (attualmente un'app console) riceve la richiesta e, per la prima volta, chiama STS per recuperare il token, lo memorizza nella cache e lo restituisce con successo al client che, successivamente, lo utilizza per chiamare l'RP. tutto funziona bene.

La seconda volta, tuttavia, il mio servizio cahce locale tenta di utilizzare nuovamente lo stesso token, ma il lato client non riesce con un MessageSecurityException -

" Il processore di sicurezza non è riuscito a trovare un'intestazione di sicurezza nel messaggio. Ciò potrebbe essere dovuto al fatto che il messaggio è un errore non garantito o perché esiste una discrepanza vincolante tra le parti comunicanti. Ciò può verificarsi se il servizio è configurato per la sicurezza e il client non utilizza la sicurezza. & Quot;

Esiste qualcosa che impedisce l'utilizzo dello stesso token più di una volta? Ne dubito perché quando ho riutilizzato il token secondo l'esempio WSTrustClient ha funzionato bene; cosa mi sto perdendo? la mia idea è possibile? una buona?

Ecco i bit di codice principali (molto basilari, in questa fase) della cache locale -

    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;
È stato utile?

Soluzione

Questo è quasi imbarazzante, ma grazie a Dominick Baier sul forum non mi rendo conto di aver perso un punto enorme (sapevo che non aveva senso! onestamente! :-)) -

Un token viene recuperato una volta per proxy di servizio, supponendo che non fosse scaduto, quindi tutto ciò che dovevo fare è riutilizzare lo stesso proxy, che avevo pianificato di fare comunque, ma, piuttosto stupidamente, non è stato eseguito sul mio prototipo.

Inoltre, ho trovato un campione molto interessante sugli esempi WCF WCF - Fornitore di token emesso durevole , che, se ho capito bene, utilizza un comportamento endpoint personalizzato sul lato client per implementare la memorizzazione dei token nella cache, che è molto elegante.

Esaminerò ancora questo approccio poiché disponiamo di numerosi servizi e quindi potremmo raggiungere un'efficienza ancora maggiore riutilizzando lo stesso token tra i loro proxy.

Quindi - due soluzioni, praticamente perplesse dei miei occhi; spero che la mia stupidità aiuti qualcuno ad un certo punto!

Altri suggerimenti

Ho fornito un esempio completo per la memorizzazione nella cache del token qui: http://blogs.technet.com/b/meamcs/archive/2011/11/20/caching-sts-security-token-with -un-attiva-web-client.aspx

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top