使用凭证卡住了连接到远程SOAP服务的过程

时间:2018-11-23 14:39:12

标签: wcf soap binding soapui wcf-binding

我需要连接到远程SOAP服务。几天来,我一直在尝试所有所有配置,但均未成功。

使用SoapUI时连接正常。 从我的.net应用程序调用时,连接为KO。

错误: 未提供用户名。在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使用以下配置:

  • 授权:基本
  • 用户名:DOMAIN \ username
  • 密码:pwd
  • Pre-Pretive身份验证

当我检查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 Behavior,该Endpoint Behavior调用了一个Inspector(来自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"解决了该错误。

编辑:要添加凭据,我正在使用该答案:Set WCF ClientCredentials in App.config

似乎可行,我正在朝着一个旧错误迈进:An error occurred when verifying security for the message.

2 个答案:

答案 0 :(得分:0)

要将用户名和密码添加到服务,则在设置服务时需要执行以下操作

// 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 Service inside aspnet webforms throwing 302

您可以从Microsoft

阅读更多内容

答案 1 :(得分:0)

解决了!!!

非常沮丧,但是写一篇SO帖子并保持更新很有帮助。

我庆祝了,我将再次详细介绍解决方案。

简而言之,请使用我在编辑中添加的链接中的实现,而不是以前的方法。