2017-02-07 4 views
0

У меня есть приложение службы WCF, которое должно подключаться к другому серверу X для извлечения данных. Когда сервер X настроен с односторонним SSL, приложение службы WCF может подключиться к нему без проблем. Но когда сервер X настроен с использованием двухстороннего SSL, приложение службы WCF будет иметь проблемы с подключением к нему.Не удается получить двухсторонний SSL для работы с HttpWebRequest

Приложение службы WCF использует самозаверяющий сертификат. Этот сертификат экспортировался без закрытого ключа в файл .cer и импортировался в хранилище доверия сервера X. Же экспортированный сертификат был использован в кодексах приложения WCF услуг:

string URL = "https://11.205.112.49:5311/Ping"; 
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(URL); 
X509Certificate2 Certificate = new X509Certificate2("F:\\cert.cer"); 
Request.ClientCertificates.Add(Certificate); 
Request.Method = "GET"; 
HttpWebResponse Response = (HttpWebResponse)Request.GetResponse(); 

Последняя строка кодов выше выбросит WebException со следующим сообщением:

The request was aborted: Could not create SSL/TLS secure channel. 

выше ошибка не дает много деталей ,

Помогите оценить.

Заранее спасибо.

EDIT:

Это вся моя программа:

using System.Net; 
using System.Security.Cryptography.X509Certificates; 
using System.IO; 

namespace TestTwoWaySSL 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      HttpWebResponse Response = null; 
      try 
      { 
       string URL = "https://11.205.112.49:5311/Ping"; 
       Console.WriteLine("URL: [{0}].", URL); 
       HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(URL); 
       X509Certificate2 Certificate = new X509Certificate2("F:\\cert.pfx", "password"); 
       Request.ClientCertificates.Add(Certificate); 
       Request.Method = "GET"; 
       Console.WriteLine("Sending request."); 
       Response = (HttpWebResponse)Request.GetResponse(); 
       Console.WriteLine("Request sent."); 
      } 
      catch (WebException webException) 
      { 
       Console.WriteLine("Web exception occurred: [{0}].", webException.Message); 
       Console.WriteLine(webException.StackTrace); 
       Response = webException.Response as HttpWebResponse; 
      } 
      catch (Exception exception) 
      { 
       Console.WriteLine("Exception occurred: [{0}].", exception.Message); 
       Console.WriteLine(exception.StackTrace); 
      } 
      Console.WriteLine("Response status code: [{0}].", Response.StatusCode); 
      Console.WriteLine("Response \"Content-Type\" header value: [{0}].", Response.ContentType); 
      Console.WriteLine("Response \"Content-Length\" header value: [{0}].", Response.ContentLength); 
      String ResponseMessageBody = new StreamReader(Response.GetResponseStream()).ReadToEnd(); 
      Console.WriteLine("Response message body: [{0}].", ResponseMessageBody); 
     } 
    } 
} 

Когда он достигает линии Request.GetResponse(), создается AccessVioationException брошено:

Unhandled Exception: System.AccessViolationException: Attempted to read or write 
protected memory. This is often an indication that other memory is corrupt. 
    at System.Net.UnsafeNclNativeMethods.SafeNetHandles_SECURITY.AcquireCredentialsHandleW(String principal, String moduleName, Int32 usage, Void* logonID, SecureCredential& authData, Void* keyCallback, Void* keyArgument, SSPIHandle& handlePtr, Int64& timeStamp) 
    at System.Net.SafeFreeCredentials.AcquireCredentialsHandle(SecurDll dll, String package, CredentialUse intent, SecureCredential& authdata, SafeFreeCredentials& outCredential) 
    at System.Net.SSPISecureChannelType.AcquireCredentialsHandle(String moduleName, CredentialUse usage, SecureCredential& authdata, SafeFreeCredentials& outCredential) 
    at System.Net.SSPIWrapper.AcquireCredentialsHandle(SSPIInterface SecModule, String package, CredentialUse intent, SecureCredential scc) 
    at System.Net.Security.SecureChannel.AcquireCredentialsHandle(CredentialUse credUsage, SecureCredential& secureCredential) 
    at System.Net.Security.SecureChannel.AcquireClientCredentials(Byte[]& thumbPrint) 
    at System.Net.Security.SecureChannel.GenerateToken(Byte[] input, Int32 offset, Int32 count, Byte[]& output) 
    at System.Net.Security.SecureChannel.NextMessage(Byte[] incoming, Int32 offset, Int32 count) 
    at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) 
    at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) 
    at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) 
    at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest) 
    at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) 
    at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) 
    at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest) 
    at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult) 
    at System.Net.TlsStream.CallProcessAuthentication(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.TlsStream.ProcessAuthentication(LazyAsyncResult result) 
    at System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size) 
    at System.Net.PooledStream.Write(Byte[] buffer, Int32 offset, Int32 size) 
    at System.Net.ConnectStream.WriteHeaders(Boolean async) 
    at System.Net.HttpWebRequest.EndSubmitRequest() 
    at System.Net.HttpWebRequest.SetRequestSubmitDone(ConnectStream submitStream) 
    at System.Net.Connection.CompleteConnection(Boolean async, HttpWebRequest request) 
    at System.Net.Connection.CompleteStartConnection(Boolean async, HttpWebRequest httpWebRequest) 
    at System.Net.Connection.CompleteStartRequest(Boolean onSubmitThread, HttpWebRequest request, TriState needReConnect) 
    at System.Net.Connection.SubmitRequest(HttpWebRequest request, Boolean forcedsubmit) 
    at System.Net.ServicePoint.SubmitRequest(HttpWebRequest request, String connName) 
    at System.Net.HttpWebRequest.SubmitRequest(ServicePoint servicePoint) 
    at System.Net.HttpWebRequest.GetResponse() 
    at TestTwoWaySSL.Program.Main(String[] args) 

ответ

1

Проблема заключается в том, что вам не хватает личного ключа. Вы используете только сертификат.

Либо использовать PKCS # 12, когда loading certificate into X509Certificate2 class

X509Certificate2 Certificate = new X509Certificate2("F:\\cert.p12", "p12 password"); 

или load certificate from store

X509Store store = new X509Store("MY",StoreLocation.CurrentUser); 
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); 

X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates; 
X509Certificate2 certificate = collection.Find(...)[0]; 
store.Close(); 
+0

Привет Pepo, я попытался оба пути, и оба пути будут бросать AccessViolationException. Посмотрите мои полные исходные коды выше и трассировку стека исключений. – user3573403

+0

ОК, я обнаружил, что мне нужно включить службу изоляции CNG Key. После включения исключения AccessViolationException исчез. Однако теперь я получаю «Основополагающее соединение было закрыто: не удалось установить доверительные отношения для безопасного канала SSL/TLS». – user3573403

+0

Я понял, что не вставил строку «ServicePointManager.ServerCertificateValidationCallback = ...». После того, как я включил его, он работает. – user3573403

Смежные вопросы