我试图向Xamarin.Android中的网络API发送请求。 api需要客户端证书。我遵循了这个问题中的建议:xamarin.ios httpclient clientcertificate not working with https,但我得到了一个未实现的方法"例外。有人可以帮忙吗?
这是我的代码:
string result = await CallApi(new System.Uri("myurl"));
protected async Task<string> CallApi(Uri url)
{
try
{
AndroidClientHandler clientHandler = new AndroidClientHandler();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Ssl3;
using (var mmstream = new MemoryStream())
{
Application.Context.Assets.Open("mycert.pfx").CopyTo(mmstream);
byte[] b = mmstream.ToArray();
X509Certificate2 cert = new X509Certificate2(b, "password", X509KeyStorageFlags.DefaultKeySet);
clientHandler.ClientCertificates.Add(cert);
}
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback((sender, certificate, chain, policyErrors) => { return true; });
HttpClient client = new HttpClient(clientHandler);
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
return responseBody;
}
catch (HttpRequestException e)
{
Console.WriteLine("\nException Caught!");
return string.Empty;
}
}
答案 0 :(得分:3)
在您提到的帖子中,可能使用了托管处理程序。由于此处理程序当前不支持TLS 1.2,因此您不应使用它,而应使用AndroidClientHandler
(另请参见Xamarin and TLS 1.2)。
不幸的是ClientCertificates
确实没有在AndroidClientHandler
中实现。
如果您想在Android上使用客户端证书,则可以扩展AndroidClientHandler
:
using Java.Security;
using Java.Security.Cert;
using Javax.Net.Ssl;
using Xamarin.Android.Net;
using Xamarin.Forms;
public class AndroidHttpsClientHandler : AndroidClientHandler
{
private SSLContext sslContext;
public AndroidHttpsClientHandler(byte[] customCA, byte[] keystoreRaw) : base()
{
IKeyManager[] keyManagers = null;
ITrustManager[] trustManagers = null;
// client certificate
if (keystoreRaw != null)
{
using (MemoryStream memoryStream = new MemoryStream(keystoreRaw))
{
KeyStore keyStore = KeyStore.GetInstance("pkcs12");
keyStore.Load(memoryStream, clientCertPassword.ToCharArray());
KeyManagerFactory kmf = KeyManagerFactory.GetInstance("x509");
kmf.Init(keyStore, clientCertPassword.ToCharArray());
keyManagers = kmf.GetKeyManagers();
}
}
// custom truststore if you have your own ca
if (customCA != null)
{
CertificateFactory certFactory = CertificateFactory.GetInstance("X.509");
using (MemoryStream memoryStream = new MemoryStream(customCA))
{
KeyStore keyStore = KeyStore.GetInstance("pkcs12");
keyStore.Load(null, null);
keyStore.SetCertificateEntry("MyCA", certFactory.GenerateCertificate(memoryStream));
TrustManagerFactory tmf = TrustManagerFactory.GetInstance("x509");
tmf.Init(keyStore);
trustManagers = tmf.GetTrustManagers();
}
}
sslContext = SSLContext.GetInstance("TLS");
sslContext.Init(keyManagers, trustManagers, null);
}
protected override SSLSocketFactory ConfigureCustomSSLSocketFactory(HttpsURLConnection connection)
{
SSLSocketFactory socketFactory = sslContext.SocketFactory;
if (connection != null)
{
connection.SSLSocketFactory = socketFactory;
}
return socketFactory;
}
}