2009-11-12 3 views
8

J'ai travaillé avec WCF ces deux derniers jours et ça se passait très bien avec le serveur et le client sur ma machine de développement. Maintenant que j'essaie de faire des tests distribués avec le client sur une autre machine du réseau, j'ai commencé à rencontrer des problèmes. En ce moment l'erreur que je reçois est:Comment désactiver par programme la sécurité dans WCF

Le message avec action « http://tempuri.org/IWindowUpdateContract/UpdateWindowFrames » ne peut pas être traité au niveau du récepteur, en raison d'un décalage de ContractFilter au EndpointDispatcher. Cela peut être dû soit à une non-concordance de contrat (Actions non concordantes entre l'expéditeur et le destinataire), soit à une non-concordance de liaison/sécurité entre l'expéditeur et le destinataire. Vérifiez que l'expéditeur et le destinataire ont le même contrat et la même liaison (y compris les exigences de sécurité, par exemple Message, Transport, Aucune).

Comme cela est déjà une expérience d'apprentissage massif (je ne l'ai pas fait de Remoting, RPC, et al avant) Je veux continuer à développer l'outil d'apprentissage et de revisiter la sécurité quand je suis fini (je n'ai pas l'intention de construire tout ce qui sera effectivement utilisé sans les bonnes pratiques de sécurité appropriées).

Notes:

  • Je n'ai pas une configuration de fichier de configuration pour WCF - Je fais tout ce programme.
  • Mon réseau ne faisant pas partie d'un domaine, les paramètres de sécurité par défaut ne fonctionnaient pas pour moi (avec net.tcp). J'utilise '.Net 3.5'.

Mon serveur est créé comme ceci:

var svh = new ServiceHost(_serviceImplementation); 

    var binding = new NetTcpBinding(); 

    binding.ReaderQuotas.MaxArrayLength = 2000000; 
    binding.Security.Mode = SecurityMode.None; 
    binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None; 
    binding.Security.Transport.ProtectionLevel = ProtectionLevel.None; 
    binding.Security.Message.ClientCredentialType = MessageCredentialType.None; 

    svh.AddServiceEndpoint(_serviceInterface, binding, string.Format("net.tcp://{0}:{1}", _endPoint.Address, _endPoint.Port)); 

    _stopFlag = new AutoResetEvent(false); 

    svh.Open(); 

    _stopFlag.WaitOne(); 

Et mon client est créé comme ceci:

var binding = new NetTcpBinding(); 

    binding.ReaderQuotas.MaxArrayLength = 2000000; 
    binding.Security.Mode = SecurityMode.None; 
    binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None; 
    binding.Security.Transport.ProtectionLevel = ProtectionLevel.None; 
    binding.Security.Message.ClientCredentialType = MessageCredentialType.None; 

    var scf = new ChannelFactory<IUserInputContract>(binding, "net.tcp://192.168.0.42:8001"); 
    _uiUpdateServer = scf.CreateChannel(); 

Et mon contrat (qui est juste dans une bibliothèque de classes qui est ajouté comme une référence au client et au serveur) est:

[ServiceContract(ProtectionLevel = ProtectionLevel.None)] 
    public interface IWindowUpdateContract { 
     [OperationContract] 
     void UpdateWindowFrames(WindowFrame frame); 
     [OperationContract] 
     void WindowHasClosed(IntPtr hwnd); 
} 

I f anguille que la configuration de liaison et de contrat que j'ai fait devrait les rendre identiques et je ne devrais pas avoir ce problème (et la sécurité devrait être éteinte). Je ne sais pas où aller maintenant.

Répondre

10

Je suis d'accord avec vous - il semblerait que les paramètres de sécurité pour le serveur et le client sont identiques.

Une note sur le côté: une fois que vous faites:

binding.Security.Mode = SecurityMode.None; 

Je ne pense pas que vous devez spécifier plus de mise sur l'objet « binding.Security » ou au-dessous - ces lignes supplémentaires après sont pas besoin.

Ce qui a attiré mon attention est votre contrat de service:

[ServiceContract(ProtectionLevel = ProtectionLevel.None)] 
public interface IWindowUpdateContract 
{ 
    [OperationContract] 
    void UpdateWindowFrames(WindowFrame frame); 
    [OperationContract] 
    void WindowHasClosed(IntPtr hwnd); 
} 

Ces opérations ne renvoient rien - c'est inhabituel. Le comportement par défaut pour un service WCF est Demande/Réponse - vous envoyez une requête et récupérez une réponse.Soit les faire retourner quelque chose (un statut ou un tel, comme une chaîne, un int), ou alors vous aurez besoin de les marquer comme des appels "à sens unique" afin que WCF sache ne rien attendre en retour:

[ServiceContract(ProtectionLevel = ProtectionLevel.None)] 
public interface IWindowUpdateContract 
{ 
    [OperationContract(IsOneWay=true)] 
    void UpdateWindowFrames(WindowFrame frame); 
    [OperationContract(IsOneWay=true)] 
    void WindowHasClosed(IntPtr hwnd); 
} 

Marc

+0

J'ai essayé d'ajouter l'attribut « IsOneWay » et moi avons aussi réduit le code de liaison à une ligne que vous avez mentionné et les choses se passent maintenant. Merci beaucoup pour votre aide! Je trouve un peu étrange que l'une ou l'autre de ces deux choses puisse avoir causé cette erreur spécifique ... mais je n'ai rien changé d'autre et maintenant ça marche! – InvertedAcceleration

+0

@curiouscoder: Je crois que ce sont les paramètres IsOneWay = true qui ont fait la différence. –

Questions connexes