私のXamarin.Androidアプリケーションは、httpsで実行されているWebサービスにリクエストを行います。証明書は自己署名されている可能性がありますので、自分で証明書のチェックを行う必要があります。自分のTrustManagerを設定しました。しかし、私が見つけたから、CheckServerTrusted
メソッドは、証明書が信頼されていない場合はCertificateException
を投げるべきです。私がそれをすると、私のアプリがクラッシュする。 CertificateException
はどこでも処理されません。カスタムで送出されたCertificateExceptionがX509TrustManagerを処理できません
var aUrl = new URL(url);
var connection = (HttpURLConnection)aUrl.OpenConnection();
try
{
var httpsConn = connection as HttpsURLConnection;
if (httpsConn != null)
{
var tm = new CustomX509TrustManager();
var sslCtx = SSLContext.GetInstance("TLSv1.2");
sslCtx.Init(null, new ITrustManager[] { tm }, null);
httpsConn.HostnameVerifier = new CustomHostnameVerifier();
httpsConn.SSLSocketFactory = sslCtx.SocketFactory;
}
System.Diagnostics.Debug.WriteLine("Connecting ...");
//connection.Connect();
await connection.ConnectAsync();
System.Diagnostics.Debug.WriteLine("Never reached");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Exception!\n{ex}");
}
finally
{
System.Diagnostics.Debug.WriteLine("Never reached");
}
System.Diagnostics.Debug.WriteLine("Never reached");
CustomX509TrustManager
は、それができるほど単純である:connection.ConnectAsync(IN
class CustomX509TrustManager : Java.Lang.Object, IX509TrustManager
{
public void CheckClientTrusted(Java.Security.Cert.X509Certificate[] chain, string authType)
{
}
public void CheckServerTrusted(Java.Security.Cert.X509Certificate[] certificates, string authType)
{
throw new Java.Security.Cert.CertificateException();
}
Java.Security.Cert.X509Certificate[] IX509TrustManager.GetAcceptedIssuers()
{
return new Java.Security.Cert.X509Certificate[0];
}
}
)リモート・サーバに接続され、証明書がCustomX509TrustManager.CheckServerTrustedにチェックされます。これにより、CertificateExceptionがスローされます。しかし、その例外は呼び出しメソッドでtry/catchで捕捉されません。このスタックトレースでアプリがクラッシュします:
UNHANDLED EXCEPTION:
Java.Security.Cert.CertificateException: Exception of type 'Java.Security.Cert.CertificateException' was thrown.
at SimpleWebRequest.MainActivity+CustomX509TrustManager.CheckServerTrusted (Java.Security.Cert.X509Certificate[] certificates, System.String authType) [0x00001] in D:\Temp\SimpleWebRequest\SimpleWebRequest\MainActivity.cs:162
at Javax.Net.Ssl.IX509TrustManagerInvoker.n_CheckServerTrusted_arrayLjava_security_cert_X509Certificate_Ljava_lang_String_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_chain, System.IntPtr native_authType) [0x00028] in /Users/builder/data/lanes/4009/9578cdcd/source/monodroid/src/Mono.Android/platforms/android-25/src/generated/Javax.Net.Ssl.IX509TrustManager.cs:129
at (wrapper dynamic-method) System.Object:5109f213-8693-4899-a3db-70ed54baf307 (intptr,intptr,intptr,intptr)
--- End of managed Java.Security.Cert.CertificateException stack trace ---
私は奇妙な結果をいくつか試しました。
私はconnection.Connect()
の代わりConnectAsync
を使用する場合は、catch
ブロックが実行されますが、finally
ブロックはもう実行されません。その後、コードではないともあります。 ConnectAsync
では、catch
ブロックも実行されません。
私がデフォルトのTrustManagerを取得し、私が私の場合と同じようにSSLSocketFactory
に設定すると、動作します。証明書は拒否され、例外がキャッチされます。だから私はちょうど間違ったスレッドでキャッチがあるとは思わない。
自分自身のTrustManagerを使用していても、CheckServerTrusted
への呼び出しをデフォルトのTrustManagerに委任した場合、例外が発生したように失敗します。
私はCustomX509TrustManager
のどちらか、または私がSSLSocketFactory
にどのように渡すかを間違っていると思います。
残念なことにカスタムTrustMangagersを検索すると、ほとんどの人はすべての証明書エラーを無視したいだけです。それは私のために働く、私は証明書をチェックし、それを拒否したい場合、問題が発生します。
もちろん、それは単純化されただけです。私のメソッドは、証明書が有効でないときにだけスローします。あなたがリンクしたページから私のコードの大部分を持っています。そこではdefaultTrustManagerもCertificateExceptionをスローします。私は事前にサーバーの証明書全体を知らない。私は拇印しか知りません。したがって、自分のlocalTrustManagerのMattsアプローチを使用することはできません。 –