简体   繁体   English

从 wcf 客户端调用需要基本 http 身份验证的 Web 服务

[英]Calling a web service that requires basic http authentication from wcf client

I have a wsdl from a web service, I generated the wcf proxy.我有一个来自 Web 服务的 wsdl,我生成了 wcf 代理。 No problem.没问题。

But I can not get my head around how to pass the user name and password.但是我不知道如何传递用户名和密码。 The webservice requires basic authentication - only username and password. Web 服务需要基本身份验证 - 仅用户名和密码。

Any help?有什么帮助吗?

Is Basic authentication configured in configuration file?配置文件中是否配置了Basic认证? Do you need to pass only credentials or do you also need secured transport (HTTPS)?您只需要传递凭据还是还需要安全传输 (HTTPS)?

First you need to set up binding to support Basic authentication首先需要设置绑定支持Basic认证

Setup for HTTP binding: HTTP 绑定的设置:

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

Setup for HTTPS binding: HTTPS 绑定的设置:

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

Client endpoint has to use defined configuration like:客户端端点必须使用定义的配置,例如:

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

Then you have to pass credentials to the proxy:然后您必须将凭据传递给代理:

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

For people (A) coming to this answer in context of .NET Core projects and (B) interested in changes in code, not in XML files:对于 (A) 在 .NET Core 项目的上下文中得出这个答案的人和 (B) 对代码而不是 XML 文件的更改感兴趣的人:

  1. Use dotnet-svcutil to scaffold code with WSDL.使用dotnet-svcutil通过 WSDL 搭建代码基架。
  2. Update GetBindingForEndpoint in Reference.cs method to enable Basic Authentication in WCF client .更新Reference.cs方法中的GetBindingForEndpoint在 WCF 客户端中启用基本身份验证
  3. Set login and password when using the client instance.使用客户端实例时设置登录名和密码。

Example codes:示例代码:

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";

Refering to the answer of @Gerard Jaryczewski in .NET Core projects, you can also use the following extension method as editing the Reference.cs can be a challenge because after each update of the Reference.cs the changes will be overwritten.参考.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;
    }
}

You can then just use it like this:然后你可以像这样使用它:

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

This should cover it: http://msdn.microsoft.com/en-us/library/ms733775.aspx (See the Client section)这应该涵盖它:http: //msdn.microsoft.com/en-us/library/ms733775.aspx (参见客户端部分)

I would say it is likely to depend on how the web service expects you to pass the information.我会说这可能取决于 Web 服务希望您如何传递信息。 After all, you are only the consumer.毕竟,你只是消费者。

Having said that, it is common is web services to have the userid and password passed in the SOAP Header.话虽如此,Web 服务通常会在 SOAP 标头中传递用户 ID 和密码。

You can refer to this link for a sample implementation of this scenario您可以参考此链接以获取此场景的示例实现

Sample Soap Message示例肥皂消息

<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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM