Question

J'ai écrit une application Silverlight 2 communiquer avec un service WCF (BasicHttpBinding).Le site hébergeant le contenu Silverlight est protégé à l'aide d'un ASP.NET Fournisseur d'appartenances.Je peux accéder à l'utilisateur actuel à l'aide de HttpContext.Actuel.De l'utilisateur.L'identité.Nom de mon service WCF, et j'ai tourné sur AspNetCompatibilityRequirementsMode.

J'ai maintenant envie d'écrire une application Windows à l'aide de l'exacte même service web.Pour gérer l'authentification j'ai activé l' Le service d'authentification, et de peuvent appeler "login" pour authentifier mes utilisateurs...Okey, tous les bons...Mais comment diable puis-je obtenir que le cookie d'authentification sur mon autre service client?!

Les deux services sont hébergés sur le même domaine

  • MyDataService.svc <- l'un traitant avec mes données
  • AuthenticationService.svc <- l'un de la windows app a appeler pour s'authentifier.

Je ne veux pas créer un nouveau service pour le client windows, ou utiliser une autre liaison...

Le Client de Services d'Application est une autre alternative, mais tous les exemples est limitée à montrer comment obtenir de l'utilisateur, de rôles et de son profil...Mais une fois que nous sommes authentifié à l'aide du Client de Services d'Application, il doit être un moyen d'obtenir que le cookie d'authentification attaché à mon service clients lors de l'appel au serveur lui-même.

Selon les commentaires des collègues la solution est d'ajouter un wsHttpBinding de point de fin, mais j'espère que je peux obtenir autour de cette...

Était-ce utile?

La solution

J'ai enfin trouvé un moyen de faire ce travail.Pour l'authentification, je suis à l'aide de la "WCF Service d'Authentification".Lors de l'authentification, le service va essayer de mettre un cookie d'authentification.J'ai besoin d'obtenir ce cookie de la réponse, et l'ajouter à toute autre demande faite à d'autres services web sur la même machine.Le code qui ressemble à ceci:

var authService = new AuthService.AuthenticationServiceClient();
var diveService = new DiveLogService.DiveLogServiceClient();

string cookieHeader = "";
using (OperationContextScope scope = new OperationContextScope(authService.InnerChannel))
{
    HttpRequestMessageProperty requestProperty = new HttpRequestMessageProperty();
    OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestProperty;
    bool isGood = authService.Login("jonas", "jonas", string.Empty, true);
    MessageProperties properties = OperationContext.Current.IncomingMessageProperties;
    HttpResponseMessageProperty responseProperty = (HttpResponseMessageProperty)properties[HttpResponseMessageProperty.Name];
    cookieHeader = responseProperty.Headers[HttpResponseHeader.SetCookie];                
}

using (OperationContextScope scope = new OperationContextScope(diveService.InnerChannel))
{
    HttpRequestMessageProperty httpRequest = new HttpRequestMessageProperty();
    OperationContext.Current.OutgoingMessageProperties.Add(HttpRequestMessageProperty.Name, httpRequest);
    httpRequest.Headers.Add(HttpRequestHeader.Cookie, cookieHeader);
    var res = diveService.GetDives();
}      

Comme vous pouvez le voir j'ai deux clients d'un service, d'un fo le service d'authentification, et un pour le service que je vais utiliser.Le premier bloc qui fera appel à la méthode de Connexion, et de saisir le cookie d'authentification de la réponse.Le deuxième bloc d'ajouter l'en-tête de la requête avant d'appeler la "GetDives" méthode de service.

Je ne suis pas heureux avec ce code à tous, et je pense que la meilleure solution pourrait être d'utiliser le "Web de Référence" au lieu de "Service de Référence" et utilisez le .NET 2.0 pile à la place.

Autres conseils

Services Web, tels que ceux créés par la WCF, sont souvent les meilleurs résultats dans les "apatrides" de manière, de sorte que chaque appel à un service Web recommence.Cela simplifie le code du serveur, comme il n'y a pas besoin d'avoir une "session" qui rappelle l'état du client.Il simplifie également le code client comme il n'y a pas besoin de détenir les billets, les cookies ou autres geegaws qui suppose quelque chose sur l'état du serveur.

La création de deux services de la manière qui est décrite introduit statefulness.Le client est soit "authentifié" ou "non authentifié", et le MyDataService.svc a savoir laquelle.

Il se trouve que j'ai trouvé de la WCF pour bien fonctionner lorsque le fournisseur d'appartenances est utilisé pour authentifier l' chaque appel à un service.Ainsi, dans l'exemple donné, vous voulez ajouter l'appartenance fournisseur d'authentification gubbins à la configuration de service pour MyDataService, et de ne pas avoir un service d'authentification à tous.

Pour plus de détails, consultez l'article MSDN ici.

[Ce qui est très attrayant à propos de ce moi, comme je suis paresseux, c'est que c'est totalement déclarative.J'ai simplement répandre la bonne configuration des entrées pour ma MembershipProvider dans l'application.config de l'application et de!bingo!tous les appels à tous les contrats dans le service sont authentifiés.]

Il est juste de noter que cela ne va pas être particulièrement rapide.Si vous utilisez SQL Server pour votre base de données d'authentification, que vous aurez au moins un, peut-être deux appels de procédures stockées par appel de service.Dans de nombreux cas (en particulier pour les liaisons HTTP) les frais généraux de l'appel du service lui-même sera plus grande;si pas, envisager de déployer votre propre mise en œuvre d'un fournisseur d'appartenances qui met en cache les requêtes d'authentification.

Une chose que cette ne pas donner est la capacité à fournir un "login" de la capacité.Pour cela, vous pouvez soit fournir un (authentifié!) contrat de service qui ne fait rien (autres que de relever une faute si l'authentification échoue), ou vous pouvez utiliser la composition du fournisseur de service décrit dans l'original de l'article en référence.

Sur le client modifier votre <binding> pour la balise de service (à l'intérieur <system.serviceModel>) pour inclure:allowCookies="true"

L'application devrait maintenant conserver les cookies et l'utiliser.Vous remarquerez que IsLoggedIn maintenant retourne vrai lorsque vous vous connectez en -- elle retourne false si vous n'êtes pas autoriser les cookies.

Il est possible de cacher une bonne partie du code supplémentaire derrière un message personnalisé à l'inspecteur et le comportement de sorte que vous n'avez pas besoin de prendre soin de bricoler avec le OperationContextScope vous-même.

Je vais essayer pour se moquer de quelque chose plus tard et l'envoyer à vous.

--larsw

Vous devriez jeter un oeil à la CookieContainer objet System.Net.Cet objet permet à un non-client de navigateur à accrocher sur les cookies.C'est ce que mon équipe a utilisé la dernière fois que nous avons rencontré ce problème.

Voici un bref article quant à la façon de l'utiliser.Il y a peut être mieux là-bas, mais ce devrait vous obtenir a commencé.

Nous sommes allés les apatrides route pour notre ensemble de services WCF et Silverlight 2 de la demande.Il est possible d'obtenir Silverlight 2 pour travailler avec les services liées aux TransportWithMessageCredential de sécurité, mais il faut un certain personnalisé code de sécurité sur le Silverlight côté.Le résultat est que toutes les applications peuvent accéder aux services en définissant simplement le nom d'utilisateur et Mot de passe dans les en-têtes de message.Cela peut être fait une fois dans une coutume IRequestChannel mise en œuvre afin que les développeurs n'ont jamais besoin de s'inquiéter à propos de la définition des valeurs elles-mêmes.Si WCF n'ont un moyen facile pour les développeurs de faire ce qui je crois est serviceProxy.De sécurité.Nom d'utilisateur et serviceProxy.De sécurité.Mot de passe ou quelque chose d'aussi simple.

J'ai écrit ce un moment en arrière, lorsque j'ai été en utilisant le Client de Services d'Application pour s'authentifier auprès des services web.Il utilise un message de l'inspecteur d'insérer l'en-tête de cookie.Il y a un fichier word avec de la documentation et un projet de démonstration.Bien que ses pas exactement ce que vous faites, c'est assez proche.Vous pouvez le télécharger à partir de ici.

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