2011-08-08 3 views
1

J'écris un service WCF avec une authentification et un gestionnaire d'erreur personnalisé. Cependant, je suis confronté à ce problème: mon implémentation de IErrorHandler n'est pas touchée lorsque l'authentification déclenche une exception, mais fonctionne très bien avec d'autres exceptions.WCF - IErrorHandler vs Authentification

L'authentification est-elle exécutée avant que IErrorHandler ne soit généré? Est-ce que j'aboie le mauvais arbre en essayant de l'obtenir pour attraper ces erreurs?

Oui, j'ai essayé (et je suis) de lancer un FaultException dans mon authentification, pas SecurityTokenException.

Répondre

1

La première chose à faire est de s'assurer que votre gestionnaire d'erreurs personnalisé est également en train d'implémenter IServiceBehavior. IServiceBehavior nécessite que vous implémentiez deux autres méthodes, mais la plus importante est "ApplyDispatchBehavior", dans laquelle vous devez ajouter ErrorHandler aux répartiteurs de canaux.

C#

public class CustomErrorHandler: IServiceBehavior, IErrorHandler 
{ 
    public bool HandleError(Exception error) 
    { 
     //Return True here if you want the service to continue on as if 
     // the error was handled 

     return true; 
    } 

    public void ProvideFault(Exception error, 
          MessageVersion version, 
          ref Message fault) 
    { 
     FaultException fe = new FaultException(
      new FaultReason(error.Message), 
      new FaultCode("Service Error")); 

     MessageFault mf = fe.CreateMessageFault(); 
     fault = Message.CreateMessage(version, mf, fe.Action); 
    } 

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, 
             ServiceHostBase serviceHostBase) 
    { 

     IErrorHandler eh = new CustomErrorHandler(); 

     foreach (ChannelDsipatcherBase cdb in serviceHostBase.ChannelDispatchers) 
     { 
      ChannelDispatcher cd = cdb as ChannelDispatcher; 
      cd.ErrorHandlers.Add(eh); 
     } 

    } 

    public void AddBindingParameters(ServiceDescription serviceDescription, 
            ServiceHostBase serviceHostBase, 
            Collection<ServiceEndpoint> endpoints, 
            BindingParameterCollection bindingParameters) 
    { 
     //Add binding parameters if you want, I am not 
    } 

    public void Validate(ServiceDescription serviceDescription, 
         ServiceHostBase serviceHostBase) 
    { 
     //Add custom fault validation here if you want 
    } 
} 

Ensuite, vous devez ajouter le CustomErrorHandler comme un comportement de service et ajouter le comportement

web.config

<system.serviceModel> 
    <extensions> 
     <behaviorExtensions> 
      <add name="ErrorHandler" 
       type="ServiceNamespace.CustomErrorHandler, ServiceNamespace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/> 
     </behaviorExtensions> 
    </extensions> 
    <behaviors> 
     <serviceBehaviors> 
      <behavior name="MyBehavior1"> 
       <!--Put other behaviors for your service here then add the next line--> 
       <ErrorHandler /> 
      </behavior> 
     </serviceBehaviors> 
    </behaviors> 
</system.serviceModel> 

De cette façon, toutes vos exceptions lancées seront converties à des défauts de revenir au client.

Dans le cas de SecurityTokenExceptions, vous ne souhaitez pas les convertir immédiatement en exceptions. Vous voulez réellement les jeter en tant que SecurityTokenExceptions dans la validation personnalisée afin que le service/serveur reconnaisse que l'autorisation de sécurité a échoué, et renvoie automatiquement comme une erreur de type "403: Accès refusé". Je ne suis pas 100% mais je pense que les éléments d'authentification et de validation personnalisés se produisent avant que les comportements de service personnalisés, comme le gestionnaire d'erreurs, soient chargés. Malheureusement, si vous avez besoin de dépanner quelque chose dans votre auth, vous devrez activer le traçage WCF sur le service, voir cet article intitulé "How to turn on WCF Tracing".

Si vous devez enregistrer des tentatives d'authentification infructueuses, vous devrez probablement les placer directement dans votre validateur personnalisé.