Meine UWP-App stellt eine Verbindung zu einem http (s) -Server her, um Daten zu übertragen. Beim Erstellen einer TLS-Verbindung bietet die HttpRequestMessage.TransportInformation Informationen über die spezifischen Fehler und das Serverzertifikat, mit denen wir eine Nachricht für den Endbenutzer anzeigen, wenn ein Fehler aufgrund eines Handshake-Fehlers auftritt.UWP HttpRequestMessage.TransportInformation fehlt
Alle oben genannten funktionierten einwandfrei, bis ich meinen dev-Computer auf Windows 10 Build 1607 aktualisierte und die App auf "Windows 10 Anniversary Edition (10.0; Build 14393)" umstellte. Früher war dies "Windows 10 (10.0; Build 10586)".
Nach dieser Änderung sind alle Felder in der HttpRequestMessage.TransportInformation null. Die Ausnahme und das entsprechende HRESULT weisen jedoch eindeutig auf den SSL-Fehler hin (in diesem Fall nicht vertrauenswürdiges Serverzertifikat).
Ich habe versucht, StreamSocket zu verwenden, und sicher genug ein SSL-Handshake-Fehler, aber die StreamSocket.Information -Eigenschaft hatte alle Felder (Server-Zertifikat, Fehler usw.) ordnungsgemäß ausgefüllt, so dass sie untersucht werden konnten.
Für das Protokoll ist das Serverzertifikat selbst signiert und verwendet SHA1 Daumen/Signatur-Algorithmus.
In den folgenden Codebeispielen gibt req.TransprtInformation in ConnectToServerHttpAsync niemals das Serverzertifikat zurück, während streamSock.Information Serverzertifikatdetails in ConnectToServerAsync bereitstellt.
Frage: Ist das ein Fehler im neueren SDK oder muss ich etwas anderes mit dem HttpClient auf Build 14393 tun, um Transportinformationen zu erhalten? Habe bei MSDN oder SO nichts über dieses Verhalten gefunden und daher nichts gepostet.
private async Task ConnectToServerHttpAsync(Uri connectUri)
{
HttpRequestMessage req = null;
try
{
using (HttpBaseProtocolFilter bpf = new HttpBaseProtocolFilter())
{
bpf.AllowUI = false;
using (HttpClient httpClient = new HttpClient(bpf))
{
req = new HttpRequestMessage(HttpMethod.Get, connectUri);
using (HttpResponseMessage res = await httpClient.SendRequestAsync(req))
{
Status = ((int)(res.StatusCode)) + " " + res.ReasonPhrase;
}
}
}
}
catch (Exception ex)
{
SocketErrorStatus eSocketErrorStatus = SocketError.GetStatus(ex.HResult);
Status = eSocketErrorStatus.ToString();
Status = req?.TransportInformation?.ServerCertificate?.ToString() ?? "No server certificate.";
}
req?.Dispose();
}
private async Task ConnectToServerAsync(Uri uriToConnect)
{
StreamSocket streamSock = new StreamSocket();
HostName hostName = new HostName(uriToConnect.Host);
try
{
await streamSock.ConnectAsync(hostName, uriToConnect.Port.ToString(), SocketProtectionLevel.Tls12);
Status = "Connected.";
streamSock.Dispose();
}
catch (Exception ex)
{
SocketErrorStatus eSocketErrorStatus = SocketError.GetStatus(ex.HResult);
Status = eSocketErrorStatus.ToString();
Status = "Certificate details:";
Status = "Friendly name: " + streamSock.Information.ServerCertificate.FriendlyName;
Status = "Issuer: " + streamSock.Information.ServerCertificate.Issuer;
Status = "SignatureAlgorithmName: " + streamSock.Information.ServerCertificate.SignatureAlgorithmName;
Status = "SignatureHashAlgorithmName: " + streamSock.Information.ServerCertificate.SignatureHashAlgorithmName;
Status = "Subject: " + streamSock.Information.ServerCertificate.Subject;
Status = "ValidFrom: " + streamSock.Information.ServerCertificate.ValidFrom.ToString();
Status = "ValidTo: " + streamSock.Information.ServerCertificate.ValidTo.ToString();
ServerCert = streamSock.Information.ServerCertificate;
}
}