WCF: mon validateur personnalisé ne peut pas être spécifié dans web.config - customUserNamePasswordValidatorType - - Impossible de charger le fichier ou l'assembly… - help?

StackOverflow https://stackoverflow.com/questions/1805702

  •  05-07-2019
  •  | 
  •  

Question

Donc, en gros, tout est opérationnel avec wsHttpBindings et mon service WCF utilisant une authentification personnalisée sur HTTPS.

Le problème que je rencontre est celui de customUserNamePasswordValidatorType:

  <serviceCredentials>
    <!-- Use our own custom validation -->
    <userNameAuthentication userNamePasswordValidationMode="Custom"
                            customUserNamePasswordValidatorType="CustomValidator.CustomUserNameValidator, CustomValidator"/>
  </serviceCredentials>

Les instructions suivantes ont été trouvées ici . 'ai aussi créé ma classe personnalisée:

namespace CustomValidator
{
    public class CustomUserNameValidator : UserNamePasswordValidator
    {
        public override void Validate(string userName, string password)
        {
            if (null == userName || null == password)
            {
                throw new ArgumentNullException();
            }


            if (!AuthenticateUser(userName, password))
                throw new SecurityTokenValidationException("Invalid Credentials");

L'erreur est " Impossible de charger le fichier ou l'assembly" CustomValidator "ou l'une de ses dépendances. Le système ne trouve pas le fichier spécifié. ", et fait référence à la fin de customUserNamePasswordValidatorType -" ..., CustomValidator ".

Je ne pensais pas que le fait d'avoir mon validateur personnalisé dans son propre espace de noms et sa propre classe posait problème, mais je ne vois pas comment faire pour que cela fonctionne.

J'ai essayé avec / sans l'espace de nom au début, permutation, etc. - rien.

Espérer qu'une autre paire d'yeux puisse comprendre cela.

Merci.

EDIT system.serviceModel

  <system.serviceModel>
    <bindings>

      <!-- wsHttpBinding -->
      <wsHttpBinding>
        <binding name="wsHttpEndpointBinding">
          <security mode="TransportWithMessageCredential">
            <transport clientCredentialType="None" />
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>

      <!-- webHttpBinding -->
      <webHttpBinding>
        <binding name="wsHttps" >
          <security mode="Transport"/>
        </binding>
      </webHttpBinding>

      <!-- Basic binding -->
      <basicHttpBinding>
        <binding name="TransportSecurity">
          <security mode="Transport">
            <message clientCredentialType="UserName"/>
            <!-- transport clientCredentialType="None"/-->
          </security>
        </binding>
      </basicHttpBinding>

      <!-- customBinding>
        <binding name="WebHttpBinding_IService">
          textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
              messageVersion="Soap12" writeEncoding="utf-8">
            <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          </textMessageEncoding>
          <httpsTransport manualAddressing="false"/>
        </binding>
      </customBinding -->
      <!-- Another custom binding -->
      <customBinding>
        <binding name="CustomMapper">
          <webMessageEncoding  webContentTypeMapperType=
                 "IndexingService.CustomContentTypeMapper, IndexingService" />
          <httpTransport manualAddressing="true" />
        </binding>
      </customBinding>
    </bindings>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" />
    <services>
      <service behaviorConfiguration="ServiceBehavior" name="Service">




        <!-- Service Endpoints -->
        <!-- since we're hosting in IIS, baseAddress is not required 
        <host>
          <baseAddresses>
            <add baseAddress="https://mysslserver.com/Service.svc"/>
          </baseAddresses>
        </host>
        -->
        <endpoint address="https://mysslserver.com/Service.svc"
                  binding="wsHttpBinding"
                  bindingConfiguration="wsHttpEndpointBinding" 
                  contract="IService"
                  name="wsHttpEndpoint">
          <!-- 
              Upon deployment, the following identity element should be removed or replaced to reflect the 
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
              automatically.
          -->
          <!--identity>
            <dns value="https://mysslserver.com"/>
          </identity-->
        </endpoint>

        <!-- endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/ -->
      </service>
    </services>
    <behaviors>

      <endpointBehaviors>
        <behavior name="webBehavior">
          <webHttp />
        </behavior>
      </endpointBehaviors>

      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <!-- Setup Security/Error Auditing -->
          <serviceSecurityAudit auditLogLocation="Application"
                suppressAuditFailure="false"
                serviceAuthorizationAuditLevel="Failure"
                messageAuthenticationAuditLevel="Failure" />

          <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"
                           httpsGetUrl="https://mysslserver.com/Service.svc"/>
          <serviceDebug includeExceptionDetailInFaults="false" />
          <serviceCredentials>
            <!-- Use our own custom validation -->
            <userNameAuthentication userNamePasswordValidationMode="Custom"
                                    customUserNamePasswordValidatorType="CustomValidator.CustomUserNameValidator, CustomValidator"/>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>

      <!-- serviceBehaviors>
        <behavior name="ServiceBehavior">
        <serviceMetadata httpsGetEnabled="true" 
                           httpsGetUrl="https://mysslserver.com/Service.svc" />
          To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information 
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior-->
    </behaviors>
  </system.serviceModel>
Était-ce utile?

La solution

J'ai décidé de lui donner un autre coup de couteau et je n'ai pas aimé avoir mon validateur personnalisé dans une autre bibliothèque.

J'ai donc créé une nouvelle classe dans App_Code et j'y suis allé ...

Ce qui suit est ce qui a réellement résolu le problème,

="CustomValidator.CustomUserNameValidator, App_Code"

Autres conseils

Lorsque vous vous référez au validateur personnalisé avec les valeurs

="CustomValidator.CustomUserNameValidator, CustomValidator"

La première valeur correspond au nom du type et la seconde au nom de l'assembly. dans lequel trouver le type. Je suggère donc que dans votre première instance votre service est actuellement dans un autre assemblage tel que MyService Dans ce cas, vous aviez vraiment besoin de votre fichier de configuration pour dire

="CustomValidator.CustomUserNameValidator, MyService"

Je soupçonne que lorsque vous avez créé votre nouvelle bibliothèque de classes pour votre validateur, vous avez appelé votre projet CustomValidator (qui sera produire un assemblage appelé CustomValidator.dll), et par conséquent votre config fonctionnera (c’est-à-dire que cela n’a rien à voir avec le fait d’être dans un bibliothèque de classes - il arrive que le nom de votre assemblée référence dans le fichier web.config est maintenant valide)

Cela semble un peu étrange, mais la solution consistait à créer une bibliothèque de classes séparée et à faire référence à sa DLL dans mon service WCF.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.ServiceModel;

/// <summary>
/// Summary description for CustomUsernamePasswordValidator
/// </summary>
namespace CustomValidator
{
    public class CustomUserNameValidator : UserNamePasswordValidator
    {
        public override void Validate(string userName, string password)
        {
            if (null == userName || null == password)
            {
                throw new ArgumentNullException();
            }


            if (!AuthenticateUser(userName, password))
                throw new SecurityTokenValidationException("Invalid Credentials");
            else
            {
                // do nothing - they're good
            }
        }

        public bool AuthenticateUser(string userName, string password)
        {
            if (userName != "userbill" || password != "passwordbill")
            {
                return false;
            }
            else
            {
                return true;
            }
        }
    }
}

J'ai ensuite ajouté une référence à System.IdentityModel et System.ServiceModel.

La section serviceCredentials du service WCF est désormais modifiée:

<serviceCredentials>
    <!-- Use our own custom validation -->
    <userNameAuthentication userNamePasswordValidationMode="Custom"
                            customUserNamePasswordValidatorType="CustomValidator.CustomUserNameValidator, CustomValidator"/>
</serviceCredentials>

L’espoir qui aide quelqu'un.

J'ai essayé cela avec des informations d'identification non valides et je m'attendais à voir mes "Informations d'identification non valides". message. Au lieu de cela, le message "Au moins un jeton de sécurité dans le message n'a pas pu être validé".

Autre que ce truc est enfin opérationnel!

Je viens de lire ceci car cela a été utile pour un POC, je devais y aller rapidement. En réponse à ELHaix ci-dessus ... cela devrait fonctionner pour assurer que votre erreur personnalisée descriptive soit renvoyée au client:

using System.ServiceModel
...    
throw new FaultException("Invalid Credentials - Custom Error");
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top