Исключение в WCF с аутентификацией по имени пользователя - PullRequest
0 голосов
/ 06 января 2020

Я пытаюсь аутентифицировать WCF с помощью пользовательских аутентификаций UserName и Password. Я следовал этому руководству Microsoft . При локальной разработке все работало хорошо, но я не могу подключиться к сервису после развертывания на сервере. Всякий раз, когда я пытаюсь получить доступ к методу в сервисе, он выдает это исключение в клиенте:

Невозможно открыть защищенный канал, поскольку при согласовании безопасности с удаленным концом возникла ошибка. Это может быть потому, что EndpointIdentity отсутствует или неправильно указан в элементе EndpointAddress, который используется для создания канала. Убедитесь, что элемент EndpointIdentity, указанный или подразумеваемый в EndpointAddress, правильно идентифицирует удаленную конечную точку.

Кажется, я сделал все, что требуется. Во-первых, я создал сертификат на клиенте с помощью следующих команд PowerShell:

New-SelfSignedCertificate -DnsName desasqlapps01.ad.impi.gob.mx -CertStoreLocation cert:\LocalMachine\My -KeySpec KeyExchange


 $CertPassword = ConvertTo-SecureString -String “PruebaCertificadoAutoFirma” -Force –AsPlainText
 Export-PfxCertificate -Cert cert:\LocalMachine\My\E7A3FCD624E6FBD74B1EB346F0A8E0CA38FA24A3 - 
 FilePath C:\testcerttramitemixto.pfx -Password $CertPassword

Я создал класс, производный от UserNamePasswordValidator в службе, и соответствующие части конфигурации службы:

    <system.web>
    <compilation debug="true" targetFramework="4.7.2" />
    <httpRuntime targetFramework="4.7.2" maxRequestLength="2147483647"/>
  </system.web>
  <system.serviceModel>
    <services>
      <service name="WS_TramiteMixto.IServiceTramiteMixto">

        <host>
          <baseAddresses>
            <add baseAddress ="http://desasqlapps01.ad.impi.gob.mx/" />
          </baseAddresses>
        </host>
        <endpoint address=""
                    binding="wsHttpBinding"
                    contract="WS_TramiteMixto.IServiceTramiteMixto"></endpoint>
        <!--<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />-->

      </service>

    </services>
    <bindings>

      <!--<basicHttpBinding>

        <binding maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" receiveTimeout="00:30:00" sendTimeout="00:30:00">

          <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="16384"/>
        </binding>
      </basicHttpBinding>-->

      <wsHttpBinding>
        <binding maxReceivedMessageSize="2147483647" receiveTimeout="00:30:00" sendTimeout="00:30:00">
          <security mode="Message">
            <message clientCredentialType="UserName" establishSecurityContext="true" />
          </security>
          <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="16384"/>
        </binding>
      </wsHttpBinding>
      <webHttpBinding>
        <binding maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"/>
      </webHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceCredentials>


            <!--The serviceCredentials behavior allows one to
          specify a custom validator for username/password
          combinations.
          -->

            <userNameAuthentication userNamePasswordValidationMode="Custom"
                                    customUserNamePasswordValidatorType="WS_TramiteMixto.TramiteMixtoPaseValidator, WS_TramiteMixto" />


            <!--The serviceCredentials behavior allows one to define a service certificate. A service certificate is used by a client to authenticate the service and provide message protection. You must specify a server certificate when passing username/passwords to encrypt the information as it is sent on the wire. Otherwise the username and password information would be sent as clear text. This configuration references the "localhost" certificate installed during the setup instructions.
          -->

            <serviceCertificate findValue="desasqlapps01.ad.impi.gob.mx" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
          </serviceCredentials>
          <dataContractSerializer maxItemsInObjectGraph ="2147483647"/>
          <!-- Para evitar revelar información de los metadatos, establezca el valor siguiente en false antes de la implementación -->
          <serviceMetadata httpGetEnabled="True" policyVersion="Policy12" />
          <!-- Para recibir detalles de los errores de la excepción para la depuración, establezca el valor siguiente en true. Establézcalo en false antes de la implementación para evitar revelar información de la excepción -->
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
      <add binding="wsHttpBinding" scheme="http"/>
      <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

Затем клиент был настроен так:

<behaviors>
      <endpointBehaviors>
        <behavior name="webHttp">
          <webHttp />
        </behavior>
        <behavior name="ClientCertificateBehavior">
          <clientCredentials>
            <serviceCertificate>

           <!-- setting the certificatevalidationmode to peerorchaintrust means that if the certificate
            is in the user's trusted people store, then it will be trusted without performing a
            validation of the certificate's issuer chain. this setting is used here for convenience so that the
            sample can be run without having to have certificates issued by a certification authority (ca).
            this setting is less secure than the default, chaintrust. the security implications of this
            setting should be carefully considered before using peerorchaintrust in production code. -->

              <authentication certificateValidationMode="PeerOrChainTrust" />
            </serviceCertificate>
          </clientCredentials>
        </behavior>

      </endpointBehaviors>
<bindings>
    <wsHttpBinding>
            <binding name="WSHttpBinding_IService1" />
            <binding name="WSHttpBinding_IServiceTramiteMixto">
              <security mode="Message">
                <message clientCredentialType="UserName" establishSecurityContext="true" negotiateServiceCredential="true" />
              </security>
            </binding>
          </wsHttpBinding>
</bindings>
<endpoint address="http://desasqlapps01.ad.impi.gob.mx/WS_TramiteMIxto/ServiceTramiteMixto.svc"
  binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServiceTramiteMixto"
  contract="ServicioTramiteMixto.IServiceTramiteMixto" name="WSHttpBinding_IServiceTramiteMixto">
      <!--<endpoint address="http://desasqlapps01.ad.impi.gob.mx/WS_TramiteMIxto/ServiceTramiteMixto.svc"
        binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServiceTramiteMixto"
        contract="ServicioTramiteMixto.IServiceTramiteMixto" name="WSHttpBinding_IServiceTramiteMixto" behaviorConfiguration="ClientCertificateBehavior">-->
        <!--<identity>
          <dns value="http://desasqlapps01.ad.impi.gob.mx/"></dns>
        </identity>-->
        <identity>
          <certificate encodedValue="AwAAAAEAAAAUAAAAN9gRCkWxQeyqhRXP90pEMclVHZcgAAAAAQAAAFUDAAAwggNRMIICOaADAgECAhAo9Mgx1zrktUgP8eprE972MA0GCSqGSIb3DQEBBQUAMCcxJTAjBgNVBAMMHGRlc2FzcWxhcHBzMDEuYWQuaW1waS5nb2IubXgwHhcNMjAwMTAzMTkzOTAzWhcNMjEwMTAzMTk1OTAzWjAnMSUwIwYDVQQDDBxkZXNhc3FsYXBwczAxLmFkLmltcGkuZ29iLm14MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArYU9MV1Au0gmf043luz5ADknADdvOI+ufk52GP+q9pW7MpcCvyaZXd0OG7EeaeUMU9WriOX/TQrWrFQjqM06EXXzixEd7cF7qU2i0W3rpccrBQrhKollkoiOkkiQuXgHjqFFUMVlpeiCwRELjHGLeVnLTEnz9RzxKTUghtqHHkVECvkwuY6jVbUAUOY0+kEHPoSyPfYnIztSfWLd6mCDdMzRJ+vhSsCbzHFBQnWGwpQj5d58+XoLz9FPssmXjl/iPzZGmw+bPt7XT1y+OYNu7W0QsXYdcNJyzjjlwieiciEm7dPq4V3lQaIxkIlkRHRG6bHldYy9EI+esqZVJs4cvQIDAQABo3kwdzAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMCcGA1UdEQQgMB6CHGRlc2FzcWxhcHBzMDEuYWQuaW1waS5nb2IubXgwHQYDVR0OBBYEFC44LUubIpku7E8LvAxzOvSQkx83MA0GCSqGSIb3DQEBBQUAA4IBAQAxs4NLEVcpg8JIqThchTGYXripNyC5twZRn/SNsgVnNV5zSMzlPpwrDdpHwPbB5QNrm8XBfAIayWP0IjjB2LyMY33gIs1dNAM6xXffWNg3m6wOwMG/QomcZvWEfdUKGLG/AVwLQ61gR9NZO6I2xeRyLc7uRM8QYsu0vASjrUKjDNaBlGXxKLEJCcqC9ybQjaVas1ICY7n4rEP9PKr6Gmck2Pva6gVYJpguihhBeN1OYIsYPABP/qRoXmU9nt7jNKnJh9IxxaPt8yhR2kMlQOunbXoV6wVKSq484/9vikk3tTni7Yb44EiFoyyxscOq/Spzq+HsVm6hitQwk/cM2ID6" />
        </identity>
      </endpoint>

Сертификат, который я поместил как в хранилище доверенных лиц на клиенте, так и в личном хранилище текущего пользователя на сервере. , но я получаю это исключение и не могу вызвать ни один из методов в службе. Я также включил трассировку в службе, но ничего не регистрируется, поэтому кажется, что клиент не может даже получить доступ к службе.

Я читал, что эта ошибка может быть вызвана LoadBalancing в IIS, где я размещаю службу как приложение, согласно этой записи Но Microsoft заявляет, что для работы с балансировкой нагрузки в IIS вы должны использовать безопасные сеансы, начиная с здесь , что я уже делаю в типе безопасности в привязках службы: <security mode="Message">

Одним из требований является проверка подлинности всех входящих запросов этой службы.

ОБНОВЛЕНИЕ: Кстати, конечная точка с комментариями, которая гласит <endpoint address="http://desasqlapps01.ad.impi.gob.mx/WS_TramiteMIxto/ServiceTramiteMixto.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServiceTramiteMixto" contract="ServicioTramiteMixto.IServiceTramiteMixto" name="WSHttpBinding_IServiceTramiteMixto" behaviorConfiguration="ClientCertificateBehavior">, является фактической конфигурацией, комментарии были добавлены позже.

@ Росс Бу sh спасибо за ваш ответ Я отредактировал веб-конфигурацию в службе, чтобы она выглядела так :

         <wsHttpBinding>
        <binding maxReceivedMessageSize="2147483647" receiveTimeout="00:30:00" sendTimeout="00:30:00">
          <security mode="Transport">
<transport clientCredentialType="Certificate"/>
        <message clientCredentialType="UserName" />
        </security>
          <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="16384"/>
        </binding>
      </wsHttpBinding>
      <webHttpBinding>
        <binding maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"/>
      </webHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <dataContractSerializer maxItemsInObjectGraph ="2147483647"/>
          <!-- Para evitar revelar información de los metadatos, establezca el valor siguiente en false antes de la implementación -->
          <serviceMetadata httpGetEnabled="True" policyVersion="Policy12" />
          <!-- Para recibir detalles de los errores de la excepción para la depuración, establezca el valor siguiente en true. Establézcalo en false antes de la implementación para evitar revelar información de la excepción -->
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
      <add binding="wsHttpBinding" scheme="http"/>

    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

Однако я не хочу знать, работает ли предложенная вами конфигурация только в https: я знаю, что получаю ошибку времени выполнения, которая заявляет

Не удалось найти базовый адрес, который соответствует схеме https для конечной точки с привязкой WSHttpBinding. Зарегистрированные схемы базовых адресов: http

, и служба сейчас не работает.

@ Ross Bu sh не берите в голову, я решил это добавить

<add binding="wsHttpBinding" scheme="https"/>

</protocolMapping>

к конфигу в сервисе

На основании полученных комментариев я wi sh перефразирую свой вопрос, в частности, я хочу знать - если кто-нибудь может сказать мне -

Является ли мой сертификат действителен? Можно ли настроить проверку пароля для имени пользователя на wcf без использования ssl?

В учебнике по Microsoft указано только:

Вам необходим сертификат сервера с именем субъекта, который содержит Полное доменное имя машины. Файл конфигурации для сервера должен быть обновлен, чтобы отражать это новое имя сертификата

Но он ничего не говорит об использовании SSL или SSL-сертификата. Спасибо в avance.

1 Ответ

0 голосов
/ 07 января 2020

Нет необходимости использовать HTTPS, так же, как вы настроили. Это реально работает. Однако мы, по крайней мере, указываем один сертификат на стороне сервера независимо от использования https или настройки сертификата службы.

<system.serviceModel>
    <services>
      <service name="WcfService3.Service1" behaviorConfiguration="mybehavior">
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="mybinding" contract="WcfService3.IService1"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="mybinding">
          <security mode="Message">
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="mybehavior">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceCredentials>
            <serviceCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" findValue="5ba5022f527e32ac02548fc5afc558de1d314cb6"/>
            <userNameAuthentication customUserNamePasswordValidatorType="WcfService3.CustUserNamePasswordVal,WcfService3" userNamePasswordValidationMode="Custom"/>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

Что я не знаю, так это то, соответствует ли ваше доменное имя сертификата имени компьютера сервера? Я предлагаю вам сгенерировать клиентский прокси-класс, добавив ссылку на службу.
https://docs.microsoft.com/en-us/dotnet/framework/wcf/accessing-services-using-a-wcf-client
Конфигурация конечной точки, созданная клиентом, автоматически добавит EndpointIdentity.

  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="WSHttpBinding_IService1">
          <security>
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://vabqia969vm:8818/Service1.svc" binding="wsHttpBinding"
        bindingConfiguration="WSHttpBinding_IService1" contract="ServiceReference1.IService1"
        name="WSHttpBinding_IService1">
        <identity>
          <certificate encodedValue="blablabla" />
<!--or,using dns to identity the server -->
          <!--<dns value="vabqia969vm"/>-->
        </identity>
      </endpoint>
    </client>

В Кроме того, пожалуйста, удалите webhttpbinding связанную конфигурацию. Это не имеет ничего общего с проблемой.
Не стесняйтесь, дайте мне знать, если проблема все еще существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...