Застрял подключение к удаленной службе SOAP с учетными данными - PullRequest
0 голосов
/ 23 ноября 2018

Мне нужно подключиться к удаленному сервису SOAP.В течение нескольких дней я безуспешно пытался всех многих конфигураций.

При использовании SoapUI соединение в порядке.Соединение - это KO при звонке из моего приложения .net.

Ошибки: Имя пользователя не указано.Укажите имя пользователя в ClientCredentials.

Мое приложение и удаленное приложение работают на IIS.

Вот удаленная привязка:

<bindings>
  <wsHttpBinding>
    <binding name="WsHttpBinding_Default" maxReceivedMessageSize="524288000" openTimeout="00:10:00" closeTimeout="00:10:00" sendTimeout="00:10:00" receiveTimeout="00:10:00">
      <security mode="TransportWithMessageCredential">
        <transport clientCredentialType="None" />
        <message clientCredentialType="UserName" establishSecurityContext="false" />
      </security>
    </binding>
  </wsHttpBinding>
</bindings>

SoapUI работает со следующей конфигурацией:

  • Авторизация: Basic
  • Имя пользователя: DOMAIN \ username
  • Пароль: pwd
  • Превентивная аутентификация

Когда я проверяю необработанный запрос от SoapUI, он отправляет это:

POST https://domain.name/TestNode/V_ServicePartenaireDS/v5.svc HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/soap+xml;charset=UTF-8;action="http://URI/getUser"
Authorization: Basic UEFSVFxzdmMtaWlzYmsdfsdfsdfphZG1pbjEyMy0t
Content-Length: 1371
Host: proxy-int.part.lan.net
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:v2="http://cnc.fr/Circe/Partenaires/v2.7">
    <soap:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
        <wsse:Security soap:mustUnderstand="true" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <wsu:Timestamp wsu:Id="TS-268FDC1861EA4F5F3C154297086643492">
                <wsu:Created>2018-11-23T11:01:06Z</wsu:Created>
                <wsu:Expires>2018-11-23T16:34:26Z</wsu:Expires>
            </wsu:Timestamp>
            <wsse:UsernameToken wsu:Id="UsernameToken-268FDC1861EA4F5F3C154297086643491">
                <wsse:Username>PART\svc-iisbackend</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">pwd</wsse:Password>
                <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">yi71/jQzUJw/lzReixSgOA==</wsse:Nonce>
                <wsu:Created>2018-11-23T11:01:06.434Z</wsu:Created>
            </wsse:UsernameToken>
        </wsse:Security>
        <wsa:Action>http://UIR/getUser</wsa:Action>
    </soap:Header>
    <soap:Body>
        <v2:getUser>
            <!--Optional:-->
            <v2:id>200785</v2:id>
        </v2:getUser>
    </soap:Body>
</soap:Envelope>

Все выше работает .


Теперь, что я делаю в своем приложении .net 4.6.1?Я пытаюсь отправить тот же запрос, который отправляет SoapUI.

Вот как я это делаю: web.config с конечными точками, привязками и расширением поведения.Расширенное поведение реализует Поведение EndPoint, которое вызывает Инспектора (из ApplyClientBehavior), из которого я использую BeforeSendRequest для добавления двух вещей:

  • SOAP-заголовок <wsse:Security />
  • Авторизация:Основной заголовок http.

Вот подробности реализации.

<system.serviceModel>
    <bindings>
        <wsHttpBinding>
            <binding name="WsHttpBinding_Default" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" openTimeout="00:10:00" closeTimeout="00:10:00" sendTimeout="00:10:00" receiveTimeout="00:10:00">
                <security mode="Transport">
                    <transport clientCredentialType="None"/>
                </security>
                <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
            </binding>
            <binding name="WsHttpBinding_Authentication" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" openTimeout="00:10:00" closeTimeout="00:10:00" sendTimeout="00:10:00" receiveTimeout="00:10:00">
                <security mode="Transport">
                    <transport clientCredentialType="Basic" />
                    <message clientCredentialType="UserName" />
                </security>
                <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
            </binding>
        </wsHttpBinding>
        <basicHttpBinding>
            <binding name="BasicHttp_Default" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" openTimeout="00:10:00" closeTimeout="00:10:00" sendTimeout="00:10:00" receiveTimeout="00:10:00" />
        </basicHttpBinding>
    </bindings>
    <extensions>
        <behaviorExtensions>
            <add name="localSecurity" type="Users.UsersImplementation.Service.ImplementationCommon.BehaviorExtensionBasicAuthent, Users.UsersImplementation"/>
        </behaviorExtensions>
    </extensions>
    <behaviors>
        <endpointBehaviors>
            <behavior name="LocalWsBehavior">
                <callbackDebug includeExceptionDetailInFaults="true" />  
                <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
                <localSecurity/>
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <client>
        <endpoint address="https://domain/TestNode/V_ServiceUser/v5.svc" behaviorConfiguration="LocalWsBehavior" binding="wsHttpBinding" bindingConfiguration="WsHttpBinding_Authentication" contract="App.UserDSContract.IServiceUserDS" name="" />
        <!--<headers>
          <wsse:Security xmlns:soap="schemas.xmlsoap.org/soap/envelope" soap:mustUnderstand="true" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <wsu:Timestamp wsu:Id="TS-268FDC1861EA4F5F3C154289160250080">
              <wsu:Created>2018-11-22T15:15:02Z</wsu:Created>
              <wsu:Expires>2018-11-22T18:33:22Z</wsu:Expires>
            </wsu:Timestamp>
            <wsse:UsernameToken wsu:Id="UsernameToken-268FDC1861EA4F5F3C154289160250079">
              <wsse:Username>PART\svc-iisbackend</wsse:Username>
              <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">pws</wsse:Password>
              <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">NcDsjgc1/cRNuHVMR7kJBw==</wsse:Nonce>
              <wsu:Created>2018-11-22T15:15:02.499Z</wsu:Created>
            </wsse:UsernameToken>
          </wsse:Security>
        </headers>
      </endpoint>-->        
    </client>
</system.serviceModel>

Вниз по цепочке класса c # мы находим этот код:

    void IClientMessageInspector.AfterReceiveReply(ref Message reply, object correlationState)
    {
        // nothing to do here
    }

    object IClientMessageInspector.BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        SoapSecurityHeader header = new SoapSecurityHeader("PART\\svc-iisbackend", "pwd");
        request.Headers.Add(header);
        HttpRequestMessageProperty httpRequestMessage;
        object httpRequestMessageObject;
        if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out httpRequestMessageObject))
        {
            httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;
            if (string.IsNullOrEmpty(httpRequestMessage.Headers[HttpRequestHeader.Authorization]))
            {
                httpRequestMessage.Headers[HttpRequestHeader.Authorization] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes("PART\\svc-iisbackend-sagre" + ":" + "admin123--")); 
            }
            request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage);
        }
        else
        {
            httpRequestMessage = new HttpRequestMessageProperty();
            httpRequestMessage.Headers.Add(HttpRequestHeader.Authorization, "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes("PART\\svc-iisbackend-sagre" + ":" + "admin123--")));
            request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage);
        }
        return header.Id;
    }

Конечный конверт SOAP на стороне удаленного сервера * таков:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
    <s:Header>
        <a:Action s:mustUnderstand="1">http://UIR/getUser</a:Action>
        <a:MessageID>urn:uuid:2b66b328-778f-4967-925a-01b75d9ab607</a:MessageID>
        <a:ReplyTo>
            <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
        </a:ReplyTo>
        <wsse:Security s:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <wsu:Timestamp wsu:Id="TS-f7abfe27c28e4209b8c028ef78bdf739">
                <wsu:Created>2018-11-23T14:37:46.59Z</wsu:Created>
                <wsu:Expires>2018-11-23T16:37:46.59Z</wsu:Expires>
            </wsu:Timestamp>
            <wsse:UsernameToken wsu:Id="UsernameToken-aff0ea1c178c4843babf4afa5cd280f6">
                <wsse:Username>PART\svc-iisbackend</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">pwd</wsse:Password>
                <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">qdiFSufkRLuPRHTwDYPzBDTu1/o=</wsse:Nonce>
                <wsu:Created>2018-11-23T14:37:46.593Z</wsu:Created>
            </wsse:UsernameToken>
        </wsse:Security>
        <a:To s:mustUnderstand="1">https://domain.url/V_ServiceUser/v5.svc</a:To>
    </s:Header>
    <s:Body>
        <getUser xmlns="http://url">
            <id>200472</id>
        </getUser>
    </s:Body>
</s:Envelope>

Я следил за многими блогами и документацией, чтобы сделать это до этого момента, и я все еще застрял: D

* Чтобы получить сообщение для попадания на сервер, мне нужно использовать конфигурацию привязки по умолчанию WsHttpBinding_Default.Когда я использую WsHttpBinding_Authentication, кажется, что удаленный сервер не обрабатывает запрос.

Я пытался поиграть с конфигурацией привязок, но пока безуспешно.

  • Что не так с моей текущей конфигурацией?
  • С помощью WsHttpBinding_Authentication я получил указанную ошибку (отредактировано: неправильно скопированная ошибка вставлена) Имя пользователя не указано.Укажите имя пользователя в ClientCredentials. Произошла ошибка при проверке безопасности сообщения.
  • При использовании WsHttpBinding_Default удаленный сервер обработал бит запроса и отклонил его со следующей ошибкой:

ошибка:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
    <s:Header>
        <a:Action s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/soap/fault</a:Action>
        <a:RelatesTo>urn:uuid:2b66b328-778f-4967-925a-01b75d9ab607</a:RelatesTo>
    </s:Header>
    <s:Body>
        <s:Fault>
            <s:Code>
                <s:Value>s:Sender</s:Value>
                <s:Subcode>
                    <s:Value xmlns:a="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:InvalidSecurity</s:Value>
                </s:Subcode>
            </s:Code>
            <s:Reason>
                <s:Text xml:lang="fr-FR">Une erreur s'est produite lors de la vérification de la sécurité du message.</s:Text>
            </s:Reason>
        </s:Fault>
    </s:Body>
</s:Envelope>

Извините за стену текста, я надеюсь, что все необходимое, чтобы получить четкое представление о моей проблеме, здесь.Большое спасибо за то, что прочитали до сих пор :)

Edit: как вы можете видеть, я также пытался поместить заголовок непосредственно в конечную точку xml, но пока безуспешно.

Редактировать: привязка вызова была неправильной, теперь она:

<binding name="WsHttpBinding_Authentication" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" openTimeout="00:10:00" closeTimeout="00:10:00" sendTimeout="00:10:00" receiveTimeout="00:10:00">
          <security mode="TransportWithMessageCredential">
            <transport clientCredentialType="Basic" />
            <message clientCredentialType="UserName" />
          </security>
          <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
        </binding>

С этой новой привязкой моя ошибка теперь:

{"globalErrors":["Message with Action 'http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT' is unknown and cannot be forwarded to the recipient. This may happen if message Action was changed, or if operation was disabled or deleted from the service contract."]}

Я не нахожу контента оэта ошибка, что происходит: /

Редактировать: Устранена ошибка путем повторного добавления establishSecurityContext="false" в привязку.

Редактировать: чтобы добавить учетные данные, я использую ответы на этот пост: Установить WCF ClientCredentials в App.config

Кажется, что работает, я делаю прогресс в направлении старой ошибки: An error occurred when verifying security for the message.

Ответы [ 2 ]

0 голосов
/ 23 ноября 2018

Решено !!!

Очень много разочарований, но написание поста SO и его обновление очень помогли.

Я отмечаю, и я вернусь, чтобы подробно рассказать о решении.

Вкратце, используйте реализацию по ссылке, которую я добавляю в мои правки, а не предыдущий способ.

0 голосов
/ 23 ноября 2018

Чтобы добавить имя пользователя и пароль к Сервису, вам нужно будет сделать следующее при настройке сервиса

// Instantiate the proxy  
Service1Client proxy = new Service1Client();

// Set the user’s credentials on the proxy  
proxy.ClientCredentials.UserName.UserName = username;  
proxy.ClientCredentials.UserName.Password = password;

Когда вы используете стандартные имя пользователя и пароль WS, я добавилответьте на мой собственный вопрос после того, как испытали ту же самую вещь, ссылка Служба WCF внутри веб-форм aspnet, выбрасывающая 302

Вы можете прочитать больше на Microsoft

...