【问题标题】:Calling a web service that requires basic http authentication from wcf client从 wcf 客户端调用需要基本 http 身份验证的 Web 服务
【发布时间】:2010-08-16 18:03:04
【问题描述】:

我有一个来自 Web 服务的 wsdl,我生成了 wcf 代理。没问题。

但是我不知道如何传递用户名和密码。 Web 服务需要基本身份验证 - 只有用户名和密码。

有什么帮助吗?

【问题讨论】:

    标签: .net wcf web-services


    【解决方案1】:

    配置文件中是否配置了基本认证?您只需要传递凭据还是还需要安全传输 (HTTPS)?

    首先您需要设置绑定以支持基本身份验证

    HTTP 绑定设置:

    <bindings>
      <basicHttpBinding>
        <binding name="BasicAuth">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Basic" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    

    HTTPS 绑定设置:

    <bindings>
      <basicHttpBinding>
        <binding name="BasicAuthSecured">
          <security mode="Transport">
            <transport clientCredentialType="Basic" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    

    客户端端点必须使用已定义的配置,例如:

    <client>
      <endpoint address="..." 
                name="..." 
                binding="basicHttpBinding" 
                bindingConfiguration="BasicAuth" 
                contract="..."  />
    </client>
    

    然后您必须将凭据传递给代理:

    proxy = new MyServiceClient();
    proxy.ClientCredentials.UserName.UserName = "...";
    proxy.ClientCredentials.UserName.Password = "...";
    

    【讨论】:

      【解决方案2】:

      对于 (A) 在 .NET Core 项目的上下文中得出此答案的人,以及 (B) 对代码更改而不是 XML 文件的更改感兴趣的人:

      1. 使用dotnet-svcutil 使用 WSDL 构建代码。
      2. 更新 Reference.cs 方法中的 GetBindingForEndpoint 以启用Basic Authentication in WCF client
      3. 使用客户端实例时设置登录名和密码。

      示例代码:

      private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
      {
          if ((endpointConfiguration == EndpointConfiguration.YourService))
          {
              System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
              result.MaxBufferSize = int.MaxValue;
              result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
              result.MaxReceivedMessageSize = int.MaxValue;
              result.AllowCookies = true;
      
              // Set Basic Authentication with HTTP protocol (for HTTPS you need "Transport"):
              result.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
              result.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
      
              return result;
          }
          throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
      }
      
      var client = new YourServiceClient();
      client.ClientCredentials.UserName.UserName = "yourservicelogin";
      client.ClientCredentials.UserName.Password = "yourservicepassword";
      

      【讨论】:

      • 我已经修改了您在此处显示的 GetBindingForEndpoint 方法,添加了我的 ClientCredentials 用户名和密码,使用提琴手检查请求并且身份验证不是我的标头的一部分。任何想法?我使用的是 HTTPS,所以我将模式设置为传输。
      • @Antonio,我认为(但我不确定)在基本身份验证的上下文中 http 和 https 之间没有区别。您必须查找未填充标题的原因。没有你的代码 - 我不知道,对不起。
      • 我已经检查过了。使用 OperationContextScope 对标头进行注入是唯一对我有用的方法。
      【解决方案3】:

      参考 .NET Core 项目中 @Gerard Jaryczewski 的回答,您也可以使用以下扩展方法,因为编辑 Reference.cs 可能是一个挑战,因为每次更新 Reference.cs 后,更改都会被覆盖。

      public static class BasicAuthenticationExtension
      {
          public static void SetBasicAuthentication<T>(this ClientBase<T> client, string userName, string password) where T : class
          {
              if (client == null) throw new ArgumentNullException(nameof(client));
              if (client.Endpoint == null || client.Endpoint.Binding == null) throw new Exception("The specified client has no binding defined!");
      
              if (client.Endpoint.Binding is BasicHttpsBinding httpsBinding)
              {
                  httpsBinding.Security.Mode = BasicHttpsSecurityMode.Transport;
                  httpsBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
              }
              else if (client.Endpoint.Binding is BasicHttpBinding httpBinding)
              {
                  httpBinding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
                  httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
              }
              else
              {
                  throw new NotSupportedException("The specified client has a binding defined which is not supporting HTTP basic authentication!");
              }
      
              client.ClientCredentials.UserName.UserName = userName;
              client.ClientCredentials.UserName.Password = password;
          }
      }
      

      然后您可以像这样使用它:

      var client = new MyServiceClient();
      client.SetBasicAuthentication("myUserName", "myPassword");
      

      【讨论】:

        【解决方案4】:

        这应该包括它:http://msdn.microsoft.com/en-us/library/ms733775.aspx (见客户端部分)

        【讨论】:

        • 该问题专门询问(HTTP)基本身份验证。您的链接参考仅演示 WSHttpBinding。 WSHttpBinding 在 SOAP 信封的标头的身份验证块中使用用户名+密码凭据,这与 (HTTP) 基本身份验证不同。
        【解决方案5】:

        我想说这很可能取决于网络服务希望您如何传递信息。 毕竟,你只是消费者。

        话虽如此,Web 服务通常会在 SOAP 标头中传递用户 ID 和密码。

        您可以参考此link 了解此场景的示例实现

        示例肥皂消息

        <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
          <soap:Header>
            <AUTHHEADER xmlns="http://tempuri.org/">
              <USERNAME>string</USERNAME>
              <PASSWORD>string</PASSWORD>
            </AUTHHEADER>
          </soap:Header>
          <soap:Body>
            <SENSITIVEDATA xmlns="http://tempuri.org/" />
          </soap:Body>
        </soap:Envelope>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-02-02
          • 2010-11-19
          • 1970-01-01
          • 1970-01-01
          • 2012-04-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多