Question

N'ayant pas encore vu beaucoup de questions liées à Genève, j'ai posté cette question dans la Forum de Genève ainsi que ...

Je travaille sur un scénario dans lequel nous avons une application Win Form avec une base d'installation étendue, qui émettra des appels fréquents à divers services hébergés par nous de manière centralisée tout au long de son fonctionnement.

Les services utilisent tous le cadre de Genève et tous les clients sont censés appeler notre STS en premier lieu pour recevoir un jeton leur permettant d'accéder aux services.

Dès l'installation, à l'aide de ws2007FederationHttpBinding, l'application peut être configurée pour extraire un jeton du STS avant chaque appel de service, mais ce n'est évidemment pas le moyen le plus efficace, car nous dupliquons presque l'effort d'appeler les services. .

J'ai également implémenté le code requis pour récupérer le jeton "manuellement". depuis l'application, puis transmettez le même jeton pré-récupéré lors de l'appel d'opérations sur les services (basé sur l'exemple WSTrustClient et sur l'aide sur le forum); cela fonctionne bien et nous avons donc une solution, mais je pense qu’elle n’est pas très élégante, car elle nécessite de construire le canal WCF dans le code, en s’éloignant de la merveilleuse configuration WCF.

Je préfère de loin l'approche ws2007FederationHttpBinding dans laquelle le client appelle simplement le service comme n'importe quel autre service WCF, sans rien savoir de Genève, et les liaisons prennent en charge l'échange de jetons.

Ensuite, quelqu'un (Jon Simpson) m'a donné [ce que je pense est] une bonne idée: ajouter un service, hébergé dans l'application elle-même, pour mettre en cache les jetons récupérés localement. Le service de cache local implémenterait le même contrat que le STS; lors de la réception d'une demande, il vérifiera si un jeton cahced existe et, le cas échéant, le renverra, sinon il appellera le «vrai» STS, récupérera un nouveau jeton, le mettra en cache et le renverra. L’application client pouvait alors toujours utiliser ws2007FederationHttpBinding, mais au lieu d’avoir le STS comme émetteur, elle aurait le cache local;

De cette façon, je pense que nous pouvons obtenir le meilleur des deux mondes - la mise en cache des jetons sans le code personnalisé spécifique au service; notre cache devrait pouvoir gérer les jetons pour tous les RP.

J'ai créé un prototype très simple pour voir si cela fonctionne et, ce qui n'est pas surprenant malheureusement - je suis un peu coincé -

Mon service local (actuellement une application de console) reçoit la demande et, pour la première fois, appelle le STS pour récupérer le jeton, le met en cache et le renvoie au client qui, par la suite, l'utilise pour appeler le RP. tout fonctionne bien.

Deuxième fois, mon service cahce local tente à nouveau d'utiliser le même jeton, mais le client échoue avec une exception MessageSecurityException -

.

"Le processeur de sécurité n'a pas pu trouver d'en-tête de sécurité dans le message. Cela peut être dû au fait que le message est une faute non sécurisée ou à une incompatibilité de liaison entre les parties en communication. Cela peut se produire si le service est configuré pour la sécurité et que le client n'utilise pas la sécurité. "

Y a-t-il quelque chose qui empêche le même jeton d'être utilisé plus d'une fois? J'en doute, car lorsque j'ai réutilisé le jeton conformément à l'exemple WSTrustClient, cela a bien fonctionné. Qu'est-ce que je rate? mon idée est-elle possible? un bon?

Voici les bits de code principal (très basiques, à ce stade) du cache 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;
Était-ce utile?

La solution

C'est presque embarrassant, mais grâce à Dominick Baier sur le forum, je ne réalise pas maintenant que j'ai manqué un point important (je savais que cela n'avait aucun sens! Honnêtement! :-)) -

Un jeton est récupéré une fois par proxy de service, en supposant qu’il n’ait pas expiré. Il ne me restait donc plus qu’à réutiliser le même proxy, ce que j’avais prévu de faire de toute façon. prototype.

De plus, j'ai trouvé un exemple très intéressant dans les exemples MSDN WCF: Fournisseur de jetons émis durable , qui, si je le comprends bien, utilise un comportement de point de terminaison personnalisé du côté client pour implémenter la mise en cache des jetons, qui est très élégante.

Je continuerai à regarder cette approche car nous avons plusieurs services et nous pourrions ainsi gagner encore en efficacité en réutilisant le même symbole entre leurs mandataires.

Donc - deux solutions, à peu près infornt de mes yeux; espérons que ma stupidité aidera quelqu'un à un moment donné!

Autres conseils

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top