2017-03-14 20 views
0

私の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を検索すると、ほとんどの人はすべての証明書エラーを無視したいだけです。それは私のために働く、私は証明書をチェックし、それを拒否したい場合、問題が発生します。

答えて

0

しかし、証明書が信頼されていない場合、CheckServerTrustedメソッドは、CertificateExceptionをスローする必要があります。私がそれをすると、私のアプリがクラッシュする。 CertificateExceptionはどこでも処理されません。

私はあなたがCheckServerTrusted方法で対処方法の問題は、正確だと思う、あなたはこのようにコード化された:これは常にスローされる

public void CheckServerTrusted(Java.Security.Cert.X509Certificate[] certificates, string authType) 
{ 
    throw new Java.Security.Cert.CertificateException(); 
} 

未処理のあなたのCheckServerTrustedメソッドが呼び出された新しいCertificateException

私はあなたがこのブログをチェックすることができると思う:Self-Signed Certificates and Xamarin.Android。私が見るところでは、CheckServerTrustedメソッドを使用して、トラストマネージャを別のトラストマネージャにラップして、他の証明書を検証できるようにすることができます。このメソッドをカスタマイズすると、そのような例外をスローする必要はありません。

+0

もちろん、それは単純化されただけです。私のメソッドは、証明書が有効でないときにだけスローします。あなたがリンクしたページから私のコードの大部分を持っています。そこではdefaultTrustManagerもCertificateExceptionをスローします。私は事前にサーバーの証明書全体を知らない。私は拇印しか知りません。したがって、自分のlocalTrustManagerのMattsアプローチを使用することはできません。 –

関連する問題