【发布时间】:2021-10-10 21:19:48
【问题描述】:
编辑:
在苦苦思索了很长时间之后,我发现了一个潜在的解决方案。截至今天(2021 年 10 月 19 日),System.ServiceModel.*** 软件包的最新稳定版本是 4.8.1,但有 4.9.0 的候选版本似乎完全解决了我在这里遇到的问题。
我检查了 .NET WCF GitHub 源代码,发现 this release candidate(版本 4.9.0-rc1.21431.2)正是我想要的。他们更新了HttpTransportBindingElement 以包含Proxy property。显然它还不是稳定版本,但它仍然可以完成工作。这样,我就可以使用如下所示的方法解决原始问题:
using (var myWsdlClient = new MyWsdlGeneratedClient())
{
var binding = myWsdlClient.Endpoint.Binding as BasicHttpBinding;
var customBinding = new CustomBinding(binding);
var htbe = customBinding.Elements.Find<HttpTransportBindingElement>();
htbe.AuthenticationScheme = AuthenticationSchemes.Basic;
htbe.ProxyAuthenticationScheme = AuthenticationSchemes.Basic;
htbe.UseDefaultWebProxy = false;
htbe.BypassProxyOnLocal = false;
htbe.Proxy = new WebProxy
{
Address = new Uri("http://myproxyaddress.com:8080"),
/* Proxy creds */
Credentials = new NetworkCredential("MyProxyUserName", "MyProxyPassword"),
BypassProxyOnLocal = false
};
myWsdlClient.Endpoint.Binding = customBinding;
/* Client creds */
myWsdlClient.ClientCredentials.UserName.UserName = "MyClientUserName";
myWsdlClient.ClientCredentials.UserName.Password = "MyClientPassword";
/* Send request */
myWsdlClient.Endpoint.Address = new EndpointAddress("https://myclientaddress.com");
myWsdlClient.doSomeAction(actionRequest); // <-- IT WORKS!!!
}
原问题:
我正在尝试通过 Web 代理发送 WCF 服务请求,并且收到错误“远程服务器返回错误:(407) 需要代理身份验证”。我已经使用 WSDL 生成了代理类,在我的 app.config 中设置了绑定/端点等(它是 BasicHttpBinding)。问题是:客户端和代理都需要基本身份验证,而我似乎只能设置客户端凭据,而不是代理。
我已经尝试过的事情:
- 我在网上看到您可以尝试在代理本身的 URL 中传递凭据。所以我以编程方式为绑定上的
ProxyAddress属性执行此操作,如下所示:
using (var myWsdlClient = new MyWsdlGeneratedClient())
{
var binding = myWsdlClient.Endpoint.Binding as BasicHttpBinding;
/* Client creds */
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
myWsdlClient.ClientCredentials.UserName.UserName = "MyClientUserName";
myWsdlClient.ClientCredentials.UserName.Password = "MyClientPassword";
/* Proxy creds */
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.Basic;
binding.UseDefaultWebProxy = false;
binding.BypassProxyOnLocal = false;
binding.ProxyAddress = new Uri("http://MyProxyUserName:MyProxyPassword@myproxyaddress.com:8080");
/* Send request */
myWsdlClient.Endpoint.Address = new EndpointAddress("https://myclientaddress.com");
myWsdlClient.doSomeAction(actionRequest); // <-- error is thrown here, inner exception is 407 HTTP response
}
- 我还尝试了使用默认 Web 代理(它有点工作)。同样,我以编程方式将其设置为:
using (var myWsdlClient = new MyWsdlGeneratedClient())
{
var binding = myWsdlClient.Endpoint.Binding as BasicHttpBinding;
/* Client creds */
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
myWsdlClient.ClientCredentials.UserName.UserName = "MyClientUserName";
myWsdlClient.ClientCredentials.UserName.Password = "MyClientPassword";
/* Proxy creds */
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.Basic;
binding.UseDefaultWebProxy = true;
binding.BypassProxyOnLocal = false;
var defaultProxyBefore = WebRequest.DefaultWebProxy;
var newProxy = new WebProxy
{
Address = new Uri("http://myproxyaddress.com:8080"),
Credentials = new NetworkCredential("MyProxyUserName", "MyProxyPassword"),
BypassProxyOnLocal = false
};
WebRequest.DefaultWebProxy = newProxy;
/* Send request */
myWsdlClient.Endpoint.Address = new EndpointAddress("https://myclientaddress.com");
try
{
myWsdlClient.doSomeAction(actionRequest);
}
finally
{
WebRequest.DefaultWebProxy = defaultProxyBefore;
}
}
第二种方法的好处是它确实有效!但是,对于我的项目的要求,这还不够。我正在开发的应用程序每秒在不同的线程上发送大量请求,其中一些通过默认代理。我不希望所有那些不相关的请求都通过我的“新”代理,它们应该继续通过默认值。
总而言之,我需要一种设置代理按请求的方法,同时还能够为客户端和代理设置基本身份验证。我对 WCF 不是很有经验,我只是偶然发现了“Custom bindings”的概念,这似乎很有希望,但我仍然没有发现它是否可以满足我的需求。非常感谢您对此的任何帮助!
【问题讨论】:
-
根据您的需要,您可以尝试过滤器吗?
标签: c# .net wcf proxy wcf-binding