如何在WCF上使用HttpTransportBindingElement设置代理凭证?

问题描述:

我使用HttpTransportBindingElement与端口80上的IIS一起编码了一个WCF服务。 只要没有使用代理,代码就可以正常工作。但是,如果客户有一个http代理,WCF客户端和服务器之间的通信在这种情况下通过发生以下错误不起作用:如何在WCF上使用HttpTransportBindingElement设置代理凭证?

'没有端点正在听......以接受该消息。这通常是由不正确的地址或SOAP操作引起的。“

只有通过代码才能使用设置!

这是我对这个问题的代码的做法,但我坚持就可以了:

bool SendClientRequest(Action<ICustomerService> channel) 
{ 

    string proxy ="my.proxy.domain:8080"; 
    string user = "user1"; 
    string password="secret"; 

    // maybe i do not need this 3 lines! 
    WebProxy webproxy = new WebProxy(proxy, true); 
    webproxy.Credentials = new NetworkCredential(user, password); 
    WebRequest.DefaultWebProxy = webproxy; 

    CustomBinding customBinding = new CustomBinding(); 
    customBinding.Elements.Add(new HttpTransportBindingElement() 
    { 

    AuthenticationSchemes.None : AuthenticationSchemes.Basic,     
    ProxyAddress = string.IsNullOrEmpty(proxy) ? null : new Uri(proxy), 
    UseDefaultWebProxy = false, 
    BypassProxyOnLocal = true, 
    TransferMode = TransferMode.Streamed, 
    MaxReceivedMessageSize = 84087406592, 
    MaxBufferPoolSize = 0x1000000, 
    MaxBufferSize = 0x1000000 

    }); 


    using (ChannelFactory<ICustomerService> factory = new 
    ChannelFactory<ICustomerService>(customBinding)) 
    { 
    IClientChannel contextChannel = null; 
    string url = "http://my.domain.de/Distribution/eService.svc", 
    EndpointAddress ep = new EndpointAddress(url); 
    ICustomerService clientChannel = factory.CreateChannel(ep);     


    contextChannel = clientChannel as IClientChannel; 
    contextChannel.OperationTimeout = TimeSpan.FromMinutes(rcvTimeout); 

    channel(clientChannel); // <- here i get the exception! 
    return true; 
    } 
} 

我尝试了几种解决方案,但似乎没有什么具体像我一样。

我想你有几个选项,其中一些我会在下面详细介绍。

首先,您可以将UseDefaultWebProxy设置为true。这意味着代理信息会从系统代理设置中自动检索,可在Internet Explorer中配置(Internet选项>连接> LAN设置>代理服务器)。如果您不需要指定代理使用的凭证,这可能是适当的。

另一种适用于我的方法是在HttpTransportBindingElement()对象内使用ProxyAuthenticationScheme属性。此属性仅在CustomBinding类中可用,并允许指定将用于对代理进行身份验证的身份验证方案。与此一起,代理服务器必须针对属性ProxyAddress进行设置。最后但并非最不重要的,要使用的凭据针对应根据所使用的身份验证方案来设置代理,因此,例如,使用AuthenticationSchemes.Ntlm将意味着设置用户名和密码属性上ChannelFactory.ClientCredentials.Windows.ClientCredential或许ChannelFactory.ClientCredentials.HttpDigest.ClientCredential

在第二种方法中,请务必注意ChannelFactory中用于与远程服务一起使用的凭证与用于代理服务器的凭证之间的区别。为了清晰起见,我在下面的代码示例中强调了这些内容:

// Example service call using a CustomBinding that is configured for client 
// authentication based on a user name and password sent as part of the message. 
var binding = new CustomBinding(); 

TransportSecurityBindingElement securityBindingElement = SecurityBindingElement.CreateUserNameOverTransportBindingElement(); 

var secureTransport = new HttpsTransportBindingElement(); 
secureTransport.UseDefaultWebProxy = false; 
secureTransport.ProxyAddress = new Uri("http://some-proxy"); 
secureTransport.ProxyAuthenticationScheme = AuthenticationSchemes.Ntlm; 

binding.Elements.Add(securityBindingElement); 
binding.Elements.Add(secureTransport); 

var endpointAddress = new EndpointAddress("https://some-service"); 

var factory = new ChannelFactory<IService>(binding, endpointAddress); 

// Credentials for authentication against the remote service 
factory.Credentials.UserName.UserName = "serviceUser"; 
factory.Credentials.UserName.Password = "abc"; 

// Credentials for authentication against the proxy server 
factory.Credentials.Windows.ClientCredential.UserName = "domain\user"; 
factory.Credentials.Windows.ClientCredential.Password = "xyz"; 

var client = factory.CreateChannel(); 
client.CallMethod();