以下 wcf 调用适用于 .NET Framework 4.8 控制台应用程序,但不适用于 .NET8 控制台应用程序。
该服务由 IIS 10 托管。在 ssl 设置中,我们将客户端证书设置为“必需”。我正在使用
Systen.ServiceModel.Http
4.10.3 包,但也在我的 .NET8 控制台项目中尝试了最新的 8.0.0 包。我也尝试以 .NET6 为目标。
IIS 日志显示:
403 7 5 15
;所以我的假设是,证书根本没有通过。
public static void Call()
{
var channelFactory = new ChannelFactory<IExtendedParameterProvisioningPort>(new BasicHttpBinding
{
MaxBufferSize = 2147483647,
MaxBufferPoolSize = 2147483647,
MaxReceivedMessageSize = 2147483647,
SendTimeout = new TimeSpan(0, 2, 0),
ReceiveTimeout = new TimeSpan(0, 1, 0),
OpenTimeout = new TimeSpan(0, 1, 0),
CloseTimeout = new TimeSpan(0, 1, 0),
Security = new BasicHttpSecurity()
{
Mode = BasicHttpSecurityMode.Transport,
Transport = new HttpTransportSecurity()
{
ClientCredentialType = HttpClientCredentialType.Certificate
}
}
}, new EndpointAddress("https://example.de:1460/MyWcfService.svc"));
channelFactory.Credentials.ClientCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindByThumbprint,
"MY-THUMBPRINT");
channelFactory.Credentials.ServiceCertificate.SslCertificateAuthentication =
new X509ServiceCertificateAuthentication
{
CertificateValidationMode = X509CertificateValidationMode.None,
};
var extendedParameterProvisioningPort = channelFactory.CreateChannel();
var serviceInfoResponse = extendedParameterProvisioningPort.GetServiceInfo(new ServiceInfoRequest());
Console.WriteLine(serviceInfoResponse.Version);
}
我收到的异常是:
The HTTP request is unauthorized with client authentication scheme 'Anonymous'.
这里有什么问题吗? .NET 6/8 还不支持客户端证书吗?
ChannelFactory
/WCF?
我遇到了一个问题,WCF 中的默认 ChannelFactory 使用过时的 HttpMessageHandler,无法通过某些证书。经过一番调查,我在this帖子中发现了一个有用的建议。
为了解决这个问题,我使用新的端点行为实现了一个解决方案。这种方法归功于 petersladek。下面是实现:
首先,定义一个新的端点行为(由petersladek):
internal class CustomizeHttpHandlerEndpointBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
bindingParameters.Add(new Func<HttpClientHandler, HttpMessageHandler>(handler =>
{
var newHandler = new SocketsHttpHandler();
// copy all properties set by WCF on it's handler (so we keep all configuration from wcf), see source
// https://github.com/dotnet/wcf/blob/main/src/System.ServiceModel.Http/src/System/ServiceModel/Channels/HttpChannelFactory.cs#L272
newHandler.AutomaticDecompression = handler.AutomaticDecompression;
newHandler.Proxy = handler.Proxy;
newHandler.UseProxy = handler.UseProxy;
newHandler.UseCookies = handler.UseCookies;
newHandler.CookieContainer = handler.CookieContainer;
newHandler.PreAuthenticate = handler.PreAuthenticate;
newHandler.Credentials = handler.Credentials;
newHandler.SslOptions.EnabledSslProtocols = handler.SslProtocols;
newHandler.SslOptions.ClientCertificates = handler.ClientCertificates;
return newHandler;
}));
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { }
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }
public void Validate(ServiceEndpoint endpoint) { }
}
最后,要集成此行为,您需要将其注册到 ChannelFactory:
channelFactory.Endpoint.EndpointBehaviors.Add(new CustomizeHttpHandlerEndpointBehavior());