代码之家  ›  专栏  ›  技术社区  ›  Jeff Dege

通过WCF调用第三方安全Web服务-身份验证问题

  •  2
  • Jeff Dege  · 技术社区  · 14 年前

    我正在编写一个针对供应商Web服务的客户端,在VisualStudio2010中使用WCF。我没有能力更改它们的实现或配置。

    在他们的测试服务器上运行时,我没有遇到任何问题。我从他们的wsdl中添加了一个服务引用,在代码中设置了url,并进行了调用:

    var client = new TheirWebservicePortTypeClient();
    client.Endpoint.Address = new System.ServiceModel.EndpointAddress(webServiceUrl);
    
    if (webServiceUsername != "")
    {
        client.ClientCredentials.UserName.UserName = webServiceUsername;
        client.ClientCredentials.UserName.Password = webServicePassword;
    }
    
    TheirWebserviceResponse response = client.TheirOperation(myRequest);
    

    简单明了。直到他们将其移动到生产服务器并配置为使用https。然后我得到了这个错误:

    The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Basic realm='.
    

    所以我去寻求帮助。我发现了这个: Can not call web service with basic authentication using wcf 。

    批准的答复表明:

    BasicHttpBinding binding = new BasicHttpBinding();
    
    binding.SendTimeout = TimeSpan.FromSeconds(25);
    
    binding.Security.Mode = BasicHttpSecurityMode.Transport;
    binding.Security.Transport.ClientCredentialType = 
                                  HttpClientCredentialType.Basic;
    
    EndpointAddress address = new EndpointAddress(your-url-here);
    
    ChannelFactory<MyService> factory = 
                 new ChannelFactory<MyService>(binding, address);
    
    MyService proxy = factory.CreateChannel();
    
    proxy.ClientCredentials.UserName.UserName = "username";
    proxy.ClientCredentials.UserName.Password = "password";
    

    这似乎也很简单。除了我试图弄清楚从wsdl生成的众多类和接口中的哪一个作为服务引用之外,我应该使用它来代替上面的“MyService”。

    我的第一次尝试是使用“TheirWebservicePortTypeClient”——我在以前的版本中实例化的类。这给了我一个运行时错误:

    The type argument passed to the generic ChannelFactory class must be an interface type.
    

    所以我深入研究了生成的代码,做了更多的研究。我看到了:

    public partial class TheirWebservicePortTypeClient
    :
        System.ServiceModel.ClientBase<TheirWebservicePortType>, 
        TheirWebservicePortType
    {
        ...
    }
    

    所以我尝试实例化ChannelFactory<>使用TheirWebservicePortType。

    这给了我编译时的错误。生成的代理没有ClientCredentials成员或TheirOperation()方法。

    所以我尝试了“System.ServiceModel.ClientBase”。

    实例化通道工厂<>它仍然给了我编译时的错误。生成的代理确实有ClientCredentials成员,但它仍然没有TheirOperation()方法。

    那么,是什么给出的呢?如何从WCF客户端向HTTPS Web服务传递用户名/密码?

    ====================编辑以解释解决方案====================

    首先,按照建议,使用TheirWebservicePortType实例化工厂,将用户名和密码添加到工厂。Credentials,而不是代理。ClientCredentials工作正常。除了一点困惑。

    也许这与wsdl的奇怪编写方式有关,但客户端类TheirWebservicePortTypeClient将TheirOperation定义为接受Request参数并返回Response结果。TheirWebservicePortType接口将TheirOperation定义为接受TheirOperation_Input参数并返回TheirOperation_Output结果,其中TheirOperation_Input包含请求成员,TheirOperation_Output包含响应成员。

    在任何情况下,如果我从传递的请求中构造了TheirOperation_Input对象,则对代理的调用成功,然后我可以从返回的TheirOperation_Output对象中提取包含的Response对象:

    TheirOperation_Output output = client.TheirOperation(new TheirOperation_Input(request));
    TheirWebserviceResponse response = output.TheirWebserviceResponse;
    
    1 回复  |  直到 9 年前
        1
  •  1
  •   Richard Blewett    14 年前

    将凭据添加到ChannelFactory凭据属性