0

J'ai mis en œuvre l'authentification personnalisée avec UserNamePasswordValidator.Authentification personnalisée WCF Problème

Selon les exigences du projet, j'ai besoin de quatre paramètres d'entrée pour l'authentification (Nom d'utilisateur, Mot de passe, SiteID, BrandID).

Mais Valider la méthode accepte seulement deux paramètres: Valider (chaîne userName, mot de passe de chaîne)

Question:

1) Comment puis-je envoyer plus de deux paramètres pour valider la méthode?

2) Existe-t-il une autre approche pour définir l'authentification WCF avec ses propres méthodes de validation?

Merci,

Ram

+0

J'ai modifié mon post pour vous montrer le code OperationContext/GenericContext . J'espère que c'est utile –

Répondre

0

1. Solution de base avec concaténation

peut être le moyen le plus rapide et plus simple est de concatenate Nom d'utilisateur, SiteID et BrandID (séparés avec/ou - et en faisant une sorte d'échappement pour empêcher l'utilisation des caractères de séparation) dans l'nom d'utilisateur en-tête et créer un CustomValidator.

--------------------------- Modifier ---------------- -----------

2. Il y a quelques façons de passer des en-têtes supplémentaires **, et utiliser OperationContext. **

Je vais vous montrer aussi comment mettre autorisations déclaratives

Pour ce faire, vous pouvez utiliser les classes de Juval Löwy. Il implémente un GenericContext<T> que vous pouvez utiliser. Encapsule les mécanismes d'accès aux en-têtes.

2.1 Créer une bibliothèque partagée

Pour partager des données de client et le serveur, passés en-têtes de savon

[DataContract] 
public class ExtraHeaders 
{ 
    [DataMember] 
    public String Username { get; set; } 
    [DataMember] 
    public String Password { get; set; } 
    [DataMember] 
    public String BranchId { get; set; } 
    [DataMember] 
    public String SiteId { get; set; } 
} 

2,2 Du côté client

passer les en-têtes supplémentaires :

static void Main(string[] args) 
{ 
// provide identity as headers 
    var extraHeaders = new ExtraHeaders 
    { 
     Username="manager", 
     Password= "password", 
     BranchId = "Branch2", 
     SiteId = "Site2" 
    }; 
    MyContractClient proxy = new MyContractClient(extraHeaders); 

    proxy.MyMethod(); 

    proxy.Close(); 
} 

La procuration doit être changé un peu (pas Visual Studio ou svcutil.exe génération):

class MyContractClient : HeaderClientBase<IMyContract, ExtraHeaders>, IMyContract 
{ 
    public MyContractClient(string key,string value) : base(key,value) 
    {} 
    public void MyMethod() 
    { 
     Channel.MyMethod(); 
    } 
} 

2.3 - Ajouter la permission déclarative sur le côté serveur

autorisation déclarative avec le
[PrincipalPermission(SecurityAction.Demand, Role = "Manager")]

class MyService : IMyContract 
{ 
    [PrincipalPermission(SecurityAction.Demand, Role = "Manager")] 
    public void MyMethod() 
    { 
     var extraHeaders = ExtraHeadersContext.Current; 
     if (extraHeaders != null) 
     { 
      //Console.WriteLine("Extra headers: (BranchId:{0}, SiteId:{1}) ", extraHeaders.BranchId, extraHeaders.SiteId); 
      Console.WriteLine("Service call from : {{{0}}}", extraHeaders.Username); 
     } 
    } 
} 

2,4 Ajouter un serviceAuthorizationBehavior coller une identité à l'utilisation

<behaviors> 
    <serviceBehaviors> 
    <behavior name="customIdentificationBehavior"> 
     <serviceAuthorization principalPermissionMode="Custom"> 
     <authorizationPolicies> 
      <add policyType="Security.HttpContextPrincipalPolicy,Host" /> 
     </authorizationPolicies> 
     </serviceAuthorization> 
    </behavior> 

2,5 Implémenter le serviceAuthorizationBehvior

Le but de ce comportement est d'attribuer un principal et une identité à l'appelant.

namespace Security 
{ 
    public class HttpContextPrincipalPolicy : IAuthorizationPolicy 
    { 
     public bool Evaluate(EvaluationContext evaluationContext, ref object state) 
     { 
      try 
      { 
       var extraHeaders = ExtraHeadersContext.Current; 
       if (extraHeaders != null) 
       { 
        IPrincipal principal = new CustomPrincipal(
         new GenericIdentity(extraHeaders.Username, "Custom Provider"),extraHeaders); 

        evaluationContext.Properties["Principal"] = principal; 
        // Put user here so it can be used for declarative access on methods 
        evaluationContext.Properties["Identities"] = new List<IIdentity>() { principal.Identity }; 
       } 
       else 
       { 
        SetAnonymousPrincipal(evaluationContext); 
       } 
      } 
      catch (Exception) 
      { 
       SetAnonymousPrincipal(evaluationContext); 
      } 
      return true; 
     } 
    } 
} 

2,6 La classe CustomPrincipal prend soin de mettre l'utilisateur dans un rôle

public class CustomPrincipal : IPrincipal 
{ 
    private ExtraHeaders headers; 
    private IIdentity identity; 

    public CustomPrincipal(IIdentity identity, ExtraHeaders headers = null) 
    { 
     this.identity = identity; 
     this.headers = headers; 
    } 
    public IIdentity Identity 
    { 
     get { return identity; } 
    } 
    public bool IsInRole(string role) 
    { 
     String[] roles; 
     if (identity.Name == "manager") 
      roles = new string[1] { "Manager" }; 
     else 
      roles = new string[1] { "User" }; 
     return roles.Contains(role); 
    } 
} 

Conclusion

Dans les coulisses, les classes de Juval lu (côté serveur) et écrire (côté client) en-tête.

Extrait, par exemple:

 if(OperationContext.Current.IncomingMessageProperties.ContainsKey(ContextMessageProperty.Name)) 
    { 
     ContextMessageProperty contextProperty = OperationContext.Current.IncomingMessageProperties[ContextMessageProperty.Name] as ContextMessageProperty; 
     if(contextProperty.Context.ContainsKey(key) == false) 
     { 
      return null; 
     } 
     return contextProperty.Context[key]; 
    } 

Lien vers le code source de travail complet: http://1drv.ms/1OqPMUM

Lien vers un excellent code de Juval Lowy: Rechercher des "liaisons de contexte comme contexte personnalisé" dans la page http://www.idesign.net/Downloads à avoir la classe GenericContext Son livre est génial si vous passez du temps sur WCF

Cordialement

+0

Merci. Va aller avec concaténation de variables. – ram

+0

Ok. Donc j'ai aussi essayé dans l'autre sens aussi. Supprimé CustomValidator. Implémenté OperationContext et passé des variables dans l'en-tête supplémentaire. Mais Comment puis-je lier les informations de l'utilisateur avec la demande actuelle. Comment puis-je implémenter Principlal Custom et Identity de cette manière. – ram

+0

Selon Löwy, vous pouvez passer à GenericContext tout T qui est un DataContract –