Дуплексная служба WCF игнорирует пользовательскую аутентификацию имени пользователя

У меня есть автономная дуплексная служба WCF, использующая NetHttpsBinding. Он настроен на использование пользовательской аутентификации по имени пользователя и паролю через UserNamePasswordValidator для аутентификации клиента и сертификат для авторизации службы. Соединение работает нормально, но 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;
        }

person Phoenix    schedule 19.12.2014    source источник
comment
Ваша конечная точка https? Если нет ... ну: stackoverflow.com/ вопросы / 12828295 /   -  person TGlatzer    schedule 19.12.2014
comment
Ну нет. WSDualHttpBinding не поддерживает транспортную безопасность, что означает отсутствие https.   -  person Phoenix    schedule 19.12.2014
comment
Если связанный SO истинен, тогда вы не сможете использовать CustomUsername Auth ..   -  person TGlatzer    schedule 19.12.2014
comment
Что я могу с этим поделать? Потому что я, конечно, хочу избежать передачи четких учетных данных. Любая привязка, поддерживающая дуплекс и SSL? Может быть, кастомная привязка?   -  person Phoenix    schedule 19.12.2014
comment
Я думаю, что netTCPbindings будет поддерживать дуплексную и транспортную безопасность: msdn.microsoft.com/en-us/library/ms731092(v=vs.110).aspx   -  person TGlatzer    schedule 20.12.2014
comment
Проблема с netTCPBinding заключается в том, что вам нужно открывать порты на стороне клиента. Вчера я узнал о netHTTPBinding по одной из присланных вами ссылок. Он поддерживает дуплекс, транспорт и безопасность сообщений, а также использует WebSockets для связи, что означает, что мне не нужно открывать порты на стороне клиента, поскольку он использует порт 80/443 для связи в обоих направлениях. Я, вероятно, собираюсь использовать это, но у меня есть некоторые проблемы с Visual Studio, которые не позволяют мне добавлять ссылку на службу, когда я переключаюсь на netHTTP с wsHTTP.   -  person Phoenix    schedule 20.12.2014
comment
Возможно, вы добавите его из другой привязки и измените app.config?   -  person TGlatzer    schedule 20.12.2014
comment
Да, я думал об этом, но это кажется отрывочным, не правда ли? Скорее всего, воспользуюсь этим, хотя и схематично, или нет, если ничего не работает.   -  person Phoenix    schedule 20.12.2014
comment
Я бы не назвал это схематичным - добавление ссылки на сервис просто вызывает svcutil для создания классов .. вы можете сделать это в одиночку, если хотите. Может быть, вы можете вызвать svcutil вручную ?!   -  person TGlatzer    schedule 20.12.2014
comment
Я просто смог подключиться с помощью netHttpsBinding, но мой UserNamePasswordValidator снова был проигнорирован (бедняга). Проблема с визуальной студией, не желающей добавлять ссылку на службу, заключалась в том, что я не зарегистрировал сертификат с портом, который я использовал для службы (поскольку я пытался использовать https).   -  person Phoenix    schedule 20.12.2014
comment
В чем именно заключается ваш вопрос? Обобщите это одним предложением.   -  person RubberDuck    schedule 20.12.2014


Ответы (1)


Если вы хотите использовать настраиваемую проверку UserNamePassword, вы должны указать WCF, какой класс будет обрабатывать проверку:

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior>
        <serviceCredentials>
          <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="CustomUsernamePasswordAuth.Service.UserNamePassValidator, CustomUsernamePasswordAuth.Service" />
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>
person TGlatzer    schedule 19.12.2014
comment
Извините, я забыл упомянуть некоторые важные детали. Я обновил вопрос сейчас. - person Phoenix; 19.12.2014