问题
I have a WCF service that I want to use to connect to an external provider's API. The Client constructor in my service looks like this:
public partial class SomePortTypeClient : System.ServiceModel.ClientBase<SomeService.ClientPortType>, SomeService.SomePortType
{
static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);
public SomePortTypeClient(string endpointUrl, TimeSpan timeout, string username, string password) :
base(SomePortTypeClient.GetBindingForEndpoint(timeout), SomePortTypeClient.GetEndpointAddress(endpointUrl))
{
this.ChannelFactory.Credentials.UserName.UserName = username;
this.ChannelFactory.Credentials.UserName.Password = password;
this.ChannelFactory.Credentials.ClientCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine,
System.Security.Cryptography.X509Certificates.StoreName.Root, System.Security.Cryptography.X509Certificates.X509FindType.FindByThumbprint, "11au2i3h3ir3o1748905");
}
The client includes a https binding like this:
private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(TimeSpan timeout)
{
var httpsBinding = new BasicHttpsBinding();
httpsBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
httpsBinding.Security.Mode = BasicHttpsSecurityMode.Transport;
var integerMaxValue = int.MaxValue;
httpsBinding.MaxBufferSize = integerMaxValue;
httpsBinding.MaxReceivedMessageSize = integerMaxValue;
httpsBinding.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
httpsBinding.AllowCookies = true;
httpsBinding.ReceiveTimeout = timeout;
httpsBinding.SendTimeout = timeout;
httpsBinding.OpenTimeout = timeout;
httpsBinding.CloseTimeout = timeout;
return httpsBinding;
}
And then the actual implementation of the client and calling the endpoint:
TimeSpan duration = new TimeSpan(0, 1, 0);
SomePortTypeClient someClient = new SomePortTypeClient("https://endpointURL", duration, "username", "password");
var response = someClient.someMethod(someParameter).Result;
I created a CSR in Windows cert manager, and the external provider provided the certificates shown in the picture below which I have imported both into my personal and root store on my local machine. It is the top certificate that I use "SetCertificate" on and locate by thumbprint in my client constructor. This certifiate is linked to the Intermediate CA which is again linked to the Root CA.
So! When I run the code and try to call the endpoint I get the following error:
I'm a bit of a noob when it comes to certificates and WCF services, so I'm not sure what could be wrong here. I have tried using the three different certificates, both from the personal and the root store. I have also tried using just basic authentication and none while also setting the username, password and certificate. The service I'm trying to call is a SOAP service.
UPDATE: It seems the certificate was not signed with the correct private key. I reimported the certificate and the error disappeard, however now I'm getting a new error that just says A security error was encountered when verifying the message
. I've looked around and it seems this is often caused by a time difference between the client/server. I'm not sure how to solve this either, so any help is appreciated.
UPDATE: I enabled WCF tracing, here is the stack trace for the exception:
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent"><System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system"><EventID>131075</EventID><Type>3</Type><SubType Name="Error">0</SubType><Level>2</Level><TimeCreated SystemTime="2019-11-25T07:12:21.8768782Z" /><Source Name="System.ServiceModel" /><Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" /><Execution ProcessName="ConsoleApp1" ProcessID="22044" ThreadID="6" /><Channel /><Computer>LAPTOP-U7FDFSNI</Computer></System><ApplicationData><TraceData><DataItem><TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error"><TraceIdentifier>https://docs.microsoft.com/dotnet/framework/wcf/diagnostics/tracing/System-ServiceModel-Diagnostics-ThrowingException</TraceIdentifier><Description>Throwing an exception.</Description><AppDomain>ConsoleApp1.exe</AppDomain><Exception><ExceptionType>System.ServiceModel.Security.SecurityNegotiationException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>Could not establish secure channel for SSL/TLS with authority 'URI'.</Message><StackTrace> at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelAsyncRequest.OnGetResponse(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.ContextAwareResult.CompleteCallback(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Net.ContextAwareResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.HttpWebRequest.SetResponse(Exception E)
at System.Net.HttpWebRequest.CheckWriteSideResponseProcessing()
at System.Net.ConnectStream.ProcessWriteCallDone(ConnectionReturnResult returnResult)
at System.Net.HttpWebRequest.WriteCallDone(ConnectStream stream, ConnectionReturnResult returnResult)
at System.Net.ConnectStream.CallDone(ConnectionReturnResult returnResult)
at System.Net.ConnectStream.IOError(Exception exception, Boolean willThrow)
at System.Net.ConnectStream.HandleWriteHeadersException(Exception e, WebExceptionStatus error)
at System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.TlsStream.ResumeIOWorker(Object result)
at System.Net.TlsStream.WakeupPendingIO(IAsyncResult ar)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.Security.SslState.FinishHandshake(Exception e, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ReadFrameCallback(AsyncProtocolRequest asyncRequest)
at System.Net.AsyncProtocolRequest.CompleteRequest(Int32 result)
at System.Net.FixedSizeReader.CheckCompletionBeforeNextRead(Int32 bytes)
at System.Net.FixedSizeReader.ReadCallback(IAsyncResult transportResult)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.ContextAwareResult.CompleteCallback(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Net.ContextAwareResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace><ExceptionString>System.ServiceModel.Security.SecurityNegotiationException: Could not establish secure channel for SSL/TLS with authority 'URI'. ---&gt; System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)
--- End of inner exception stack trace ---</ExceptionString><InnerException><ExceptionType>System.Net.WebException, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>The request was aborted: Could not create SSL/TLS secure channel.</Message><StackTrace> at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)</StackTrace><ExceptionString>System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)</ExceptionString></InnerException></Exception></TraceRecord></DataItem></TraceData></ApplicationData></E2ETraceEvent>
来源:https://stackoverflow.com/questions/58969598/wcf-service-unable-to-establish-trust-relationship-for-the-ssl-tls-secure-channe