WCF双工服务忽略自定义用户名身份验证

时间:2014-12-19 12:25:24

标签: c# wcf authentication duplex

我有一个使用NetHttpsBinding的自托管WCF双工服务。它设置为通过UserNamePasswordValidator使用自定义用户名/密码身份验证进行客户端身份验证,并使用证书进行服务授权。 Connection工作正常,但从不调用UserNamePasswordValidator,因此我可以使用任何用户名和密码组合进行连接。所以我的问题是为什么它忽略了我的UserNameValidator?

以下是该服务的完整配置文件:

<?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方法:

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;
        }

1 个答案:

答案 0 :(得分:0)

如果要使用自定义UserNamePassword验证,则必须告诉WCF哪个类将处理验证:

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