Sto tentando di effettuare chiamate HTTP a un server che richiede una connessione SSL bidirezionale (autenticazione client). Ho un file .p12 che contiene più di un certificato e una password. La richiesta viene serializzata utilizzando il buffer del protocollo.Autenticazione a due vie con HTTPClient
Il mio primo pensiero è stato quello di aggiungere il keystore alle proprietà ClientCertificate del WebRequestHandler utilizzato da HttpClient. Ho anche aggiunto il keystore alle mie autorità di certificazione radice attendibili sul mio computer.
Ricevo sempre un "impossibile creare un canale sicuro ssl/tls" quando viene eseguito PostAsync. C'è ovviamente qualcosa che faccio di sbagliato, ma qui sono un po 'in perdita.
Qualsiasi suggerimento sarebbe apprezzato.
public void SendRequest()
{
try
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
var handler = new WebRequestHandler();
// Certificate is located in bin/debug folder
var certificate = new X509Certificate2Collection();
certificate.Import("MY_KEYSTORE.p12", "PASSWORD", X509KeyStorageFlags.DefaultKeySet);
handler.ClientCertificates.AddRange(certificate);
handler.ServerCertificateValidationCallback = ValidateServerCertificate;
var client = new HttpClient(handler)
{
BaseAddress = new Uri("SERVER_URL")
};
client.DefaultRequestHeaders.Add("Accept", "application/x-protobuf");
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/x-protobuf");
client.Timeout = new TimeSpan(0, 5, 0);
// Serialize protocol buffer payload
byte[] protoRequest;
using (var ms = new MemoryStream())
{
Serializer.Serialize(ms, MyPayloadObject());
protoRequest = ms.ToArray();
}
var result = await client.PostAsync("/resource", new ByteArrayContent(protoRequest));
if (!result.IsSuccessStatusCode)
{
var stringContent = result.Content.ReadAsStringAsync().Result;
if (stringContent != null)
{
Console.WriteLine("Request Content: " + stringContent);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None)
return true;
Console.WriteLine("Certificate error: {0}", sslPolicyErrors);
// Do not allow this client to communicate with unauthenticated servers.
return false;
}
EDIT
non ho neanche rompere in ValidateServerCertificate. L'eccezione viene generata non appena viene chiamato PostAsync. Il protocollo è sicuramente TLS v1.
Il sistema operativo client è Windows 8.1. Server è codificato in Java (non sono sicuro su quale sistema operativo è in esecuzione su. Non ho accesso ad esso. E 'una scatola nera.)
Stacktrace
a System.Net.HttpWebRequest.EndGetRequestStream (IAsyncResult asyncResult, TransportContext & contesto) a System.Net.Http.HttpClientHandler.GetRequestStreamCallback (IAsyncResult ar)
non c'è eccezione interna.
Chi è l'emittente del certificato archiviato nel file .P12? il server si fida di tale emittente? –
Viene emesso dal proprietario del server a cui sto tentando di connettermi (mi hanno dato il file). – Mathieu
ValidateServerCertificate restituisce 'true' o' false'? Puoi inserire un breakpoint e controllare? Nel caso in cui restituisca false, qual è il valore di sslPolocyErrors? prova a restituire sempre 'true' dal metodo solo per verificare se questo risolve il problema? Forse la tua macchina locale non si fida dell'emittente del certificato del server? –