WCF duplex service ignores custom username authentication

I have a standalone WCF service using NetHttpsBinding. It is configured to use custom username / password authentication with UserNamePasswordValidator for client authentication and certificate for service authorization. The connection works fine, but the UserNamePasswordValidator is never called, so I can connect with any combination of username and password. So my question is, why is it ignoring my UserNameValidator?

Here is the complete configuration file for the service:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
  </configSections>
  <system.serviceModel>
    <services>
      <service name="SchoolTestMaker.Service.SchoolTestMakerService">
        <endpoint address="" binding="netHttpsBinding" bindingConfiguration="netHttpsEndpointBinding" contract="SchoolTestMaker.Service.ISchoolTestMakerService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
          <serviceDebug includeExceptionDetailInFaults="True" />
          <!--<serviceAuthorization principalPermissionMode="Custom" />-->
          <serviceCredentials>
            <serviceCertificate findValue="**classified(FBI)**"/>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <netHttpsBinding>
        <binding name="netHttpsEndpointBinding">
          <security mode="TransportWithMessageCredential">
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
      </netHttpsBinding>
    </bindings>
  </system.serviceModel>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
</configuration>

      

UserNamePasswordValidator:

public class SchoolTestMakerServiceUserNamePasswordValidator:UserNamePasswordValidator
    {
        IUnitOfWork unitOfWork;
        IHashGenerator hashGenerator;
        public SchoolTestMakerServiceUserNamePasswordValidator(IUnitOfWork unitOfWork,IHashGenerator hashGenerator)
        {
            this.unitOfWork = unitOfWork;
            this.hashGenerator = hashGenerator;
        }
        public override void Validate(string userName, string password)
        {
            throw new Exception();
            /*if(userName==null||password==null)
            {
                throw new ArgumentNullException();
            }
            string passwordHash = hashGenerator.GenerateHash(password);
            UserAccount userAccount = unitOfWork.Repository<UserAccount>().Get(x => x.UserName == userName && x.PasswordHash == passwordHash);
            if(userAccount==null)
            {
                throw new SecurityTokenException("Unknown Username or Incorrect Password");
            }*/
        }
    }

      

StartService method:

public void StartService()
        {
            serviceHost = new UnityServiceHost(container,
                typeof(SchoolTestMakerService), new Uri(endpointAddress));

            //Console.WriteLine(((WSDualHttpBinding)serviceHost.Description.Endpoints[0].Binding).Security.Message.ClientCredentialType);

            serviceHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
            serviceHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = userNamePasswordValidator;

            /*var externalAuthorizationPolicies = new ReadOnlyCollection<IAuthorizationPolicy>(new IAuthorizationPolicy[] { authorizationPolicy });
            ServiceAuthorizationBehavior authorizationBehavior=serviceHost.Description.Behaviors.Find<ServiceAuthorizationBehavior>();
            authorizationBehavior.ExternalAuthorizationPolicies = externalAuthorizationPolicies;*/

            serviceHost.Open();
            ServiceRunning = true;
        }

      

+3


source to share


1 answer


If you want to use a custom UserNamePassword Validation, you must tell WCF which class will handle the validation:



<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior>
        <serviceCredentials>
          <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="CustomUsernamePasswordAuth.Service.UserNamePassValidator, CustomUsernamePasswordAuth.Service" />
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

      

0


source







All Articles