访问在Xamarin中定位Android的客户端证书的REST服务

时间:2018-03-02 15:00:00

标签: c# android xamarin httpclient

有没有人知道实现访问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项目中正常工作,但相同的代码在设备上不起作用。

1 个答案:

答案 0 :(得分:1)

您可以尝试AndroidClientHandlerProgramatically 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();
    }
 }