有没有人知道实现访问REST服务的最佳方式,该服务在Xamarin中定位Android的客户端证书?我使用.NET Standard 2.0项目作为共享代码。
我已经尝试过WebRequestHandler来添加证书,但mono似乎不支持这个并且应用程序不会运行。我也试过HttpClientHandler。
以下代码段:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
X509Certificate2 certificate = App.CertificateFile;
var handler = new WebRequestHandler
{
ClientCertificateOptions = ClientCertificateOption.Manual
};
handler.ClientCertificates.Add(certificate);
var client = new HttpClient(handler);
这里有一个类似的问题Using custom SSL client certificates System.Net.HttpClient on Mono ,但不久之前,希望事情有所改善。如果通过控制台应用程序调用,我的代码可以从.Standard 2.0项目中正常工作,但相同的代码在设备上不起作用。
答案 0 :(得分:1)
您可以尝试AndroidClientHandler和Programatically using androidClientHandler:
AndroidClientHandler clientHandler = new AndroidClientHandler();
Java.Security.Cert.X509Certificate cert = null;
try
{
CertificateFactory factory = CertificateFactory.GetInstance("X.509");
using (var stream = Application.Context.Assets.Open("MyCert.pfx"))
{
cert = (Java.Security.Cert.X509Certificate)factory.GenerateCertificate(stream);
}
} catch (Exception e)
{
System.Console.WriteLine(e.Message);
}
if (clientHandler.TrustedCerts != null)
{
clientHandler.TrustedCerts.Add(cert);
}
else
{
clientHandler.TrustedCerts = new List<Certificate>();
clientHandler.TrustedCerts.Add(cert);
}
HttpClient client = new HttpClient(clientHandler);
更新
如果up代码不起作用,您可以尝试Android Native实现,它使用与AndroidClientHandler
相同的功能,但使用起来更灵活:
var keyStore = KeyStore.GetInstance("PKCS12");
string clientCertPassword = "password_of_certificate";
using (var stream = Application.Context.Assets.Open("cert.pfx"))
{
keyStore.Load(stream, clientCertPassword.ToCharArray());
}
KeyManagerFactory kmf = KeyManagerFactory.GetInstance("x509");
kmf.Init(keyStore, clientCertPassword.ToCharArray());
IKeyManager[] keyManagers = kmf.GetKeyManagers();
SSLContext sslContext = SSLContext.GetInstance("TLS");
sslContext.Init(keyManagers, null, null);
String result = null;
HttpURLConnection urlConnection = null;
HttpStatus lastResponseCode;
try
{
URL requestedUrl = new URL("https://10.106.92.42:444");
urlConnection = (HttpURLConnection)requestedUrl.OpenConnection();
if (urlConnection is HttpsURLConnection) {
((HttpsURLConnection)urlConnection).SSLSocketFactory = sslContext.SocketFactory;
}
urlConnection.RequestMethod = "GET";
urlConnection.ConnectTimeout = 1500;
urlConnection.ReadTimeout = 1500;
lastResponseCode = urlConnection.ResponseCode;
result = ReadFully(urlConnection.InputStream);
string lastContentType = urlConnection.ContentType;
}
catch (Exception ex)
{
result = ex.ToString();
}
finally
{
if (urlConnection != null)
{
urlConnection.Disconnect();
}
}