WCF: Impossibile trovare il mio validatore personalizzato specificato in web.config - customUserNamePasswordValidatorType - - Impossibile caricare il file o l'assembly & # 8230; - Aiuto?

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

  •  05-07-2019
  •  | 
  •  

Domanda

Quindi ho praticamente tutto funzionato con wsHttpBindings e il mio servizio WCF usando l'autenticazione personalizzata su HTTPS.

Il problema che sto riscontrando riguarda customUserNamePasswordValidatorType:

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

Trovate le seguenti indicazioni qui I ho creato anche la mia classe personalizzata:

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'errore è " Impossibile caricare il file '' CustomValidator '' o una delle sue dipendenze. Il sistema non è in grado di trovare il file specificato. " ;, e fa riferimento alla fine del customUserNamePasswordValidatorType - " ..., CustomValidator " ;.

Non pensavo che fosse un problema avere il mio validatore personalizzato nel suo spazio dei nomi e classe, ma non riesco a vedere cos'altro fare per farlo funzionare.

Ho provato con / senza lo spazio dei nomi all'inizio, scambiando, ecc. niente.

Spero che un altro paio di occhi riesca a distinguerlo.

Grazie.

Modifica 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>
È stato utile?

Soluzione

Ho deciso di dargli un'altra pugnalata e non mi è piaciuto avere il mio validatore personalizzato in un'altra libreria.

Quindi ho creato una nuova classe in App_Code e ci sono andata ...

Quello che segue è ciò che l'ha risolto,

="CustomValidator.CustomUserNameValidator, App_Code"

Altri suggerimenti

Quando fai riferimento al validatore personalizzato con i valori

="CustomValidator.CustomUserNameValidator, CustomValidator"

Il primo valore è il nome del tipo e il secondo è il nome dell'assembly in cui trovare il tipo. Quindi lo suggerirei in primo luogo il tuo servizio è attualmente in qualche altro assemblaggio come MyService In quel caso avevi davvero bisogno del tuo file di configurazione per dire

="CustomValidator.CustomUserNameValidator, MyService"

Sospetto che quando avrai creato la tua nuova libreria di classi per il tuo validatore, hai chiamato il tuo progetto CustomValidator (che lo farà output un assembly chiamato CustomValidator.dll), e quindi ora tuo config funzionerà (cioè non ha nulla a che fare con l'essere in un separato libreria di classi - capita solo che la denominazione dell'assembly il riferimento in web.config è ora valido)

Sembra un po 'strano, ma la soluzione era creare una libreria di classi separata e fare riferimento alla sua DLL nel mio servizio 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;
            }
        }
    }
}

Ho quindi aggiunto un riferimento a System.IdentityModel e System.ServiceModel.

La sezione serviceCredentials per il servizio WCF è ora cambiata in questo:

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

Spero che aiuti qualcuno.

L'ho provato con credenziali non valide e mi aspettavo di vedere le mie " Credenziali non valide " Messaggio. Invece sto ricevendo " Almeno un token di sicurezza nel messaggio non può essere convalidato. & Quot;

A parte questo, questa cosa è finalmente operativa!

Semplicemente leggendo questo dato che è stato utile per un POC ho dovuto iniziare rapidamente. In risposta a ELHaix sopra ... questo dovrebbe funzionare per garantire che il tuo errore descrittivo personalizzato venga restituito al client:

using System.ServiceModel
...    
throw new FaultException("Invalid Credentials - Custom Error");
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top