6

Androidのトラストマネージャーを上書きしようとしています。基になるトラストマネージャーに証明書をチェックさせたいのですが、証明書の有効期限が切れているかどうかを判断する必要があります。証明書の有効期限が切れている場合は、それを無視して証明書を受け入れる必要があります。一部のモバイルデバイスでは、バッテリーを取り外すと日付が古い日付にリセットされ、証明書の有効期限が切れたように見えます。これが発生した場合でも、アプリは実行を継続する必要があります。

私が抱えている問題は、このコード行がNullPointerExceptionをスローすることです。

origTrustmanager.checkServerTrusted(certs, authType);

ドキュメントによると、checkServerTrustedは決してNullPointerExeptionをスローするべきではありません。certsには2つのアイテムが含まれています。authTypeは「RSA」に設定されています。カスタムのTrustManagerを実装しない場合、証明書の有効期限が切れたことを明確に示す例外がスローされるため、基盤となるTrustManagerがその役割を果たしていることがわかります。デバイスの日付と時刻を証明書の有効期間内に設定した場合でも、上記のcheckServerTrusted行で例外が生成されます。なんで?明らかに私は何か間違ったことをしている。カスタムTrustManagerのコードと、URLにアクセスする方法は次のとおりです。

class SSLTrustManager
{
  private X509TrustManager origTrustmanager;

  public SSLTrustManager()
  {
    try
    {
      TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
      tmf.init((KeyStore) null);
      TrustManager[] trustManagers = tmf.getTrustManagers();
      this.origTrustmanager = (X509TrustManager) trustManagers[0];
    }
    catch (Exception ex)
    {
    }
  }

  public javax.net.ssl.SSLSocketFactory GetSocketFactory()
  {
    try
    {
      TrustManager[] wrappedTrustManagers = new TrustManager[] {
          new X509TrustManager()
          {
            public java.security.cert.X509Certificate[] getAcceptedIssuers()
            {
              return origTrustmanager.getAcceptedIssuers();
            }

            public void checkClientTrusted(X509Certificate[] certs, String authType)
            {
              try
              {
                origTrustmanager.checkClientTrusted(certs, authType);
              }
              catch (CertificateException e)
              {
              }
            }

            public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException
            {
              try
              {
                origTrustmanager.checkServerTrusted(certs, authType);
              }
              catch(Exception ex)
              {
              }
            }
          }
       };

      SSLContext sslContext = SSLContext.getInstance("SSL");
      sslContext.init(null, wrappedTrustManagers, new java.security.SecureRandom());
      javax.net.ssl.SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
      return sslSocketFactory;
    }
    catch (Exception ex)
    {
      return null;
    }
  }
}    

URLにアクセスするためのコード:

SSLTrustManager sslTrustManager = new SSLTrustManager();
HttpsURLConnection.setDefaultSSLSocketFactory(sslTrustManager.GetSocketFactory());

URL siteUrl = new URL(url);
HttpsURLConnection conn = (HttpsURLConnection) siteUrl.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setDoInput(true);

DataOutputStream out = new DataOutputStream(conn.getOutputStream());
4

2 に答える 2

4

インスタンス変数を初期化しない場合origTrustmanager、デフォルト値はになります。これにより、インスタンス変数nullを使用しようとするたびにNPEが発生します。

TrustManagerの初期化の例を示すために、これに関する以前の回答を編集しました。(Androidで試したことはありませんが、プレーンJavaでは問題なく動作します。)

捕まえすぎないように注意してください。ここで、あなたはあなたのトラストマネージャーを捕まえCertificateExceptionExceptionいます:これらのメソッドはそれらの例外をスローすることを意図しているので、これは何もないのと同じくらい良いです。CertificateExpiredException有効期限を無視したい場合にのみキャッチするようにしてください。

これは、実際には、証明書の検証が一般的な信頼の検証の後に行われるという事実に依存するトリックにすぎないことに注意してください(少なくともOpenJDKの実装では)。私の知る限り、証明書の有効期限が。の後に検証されるという仕様には何もありません。これは、信頼の要素に関する他の検証の前に行われ、その例外を無視すると、必要以上の証明書を通過させることができます。

于 2012-12-06T11:04:39.673 に答える
-1

このコードを使用してくださいこれは私のために働いています

TrustManager tm = new X509TrustManager() {
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
};

// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {
    new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }
        public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
        public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
    }
};
SSLContext sslContext = null;

try {
    sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, new TrustManager[] { tm }, null);
} catch (Exception e1) {
    e1.printStackTrace();
    return;
}

AsyncSSLSocketMiddleware sslMiddleWare = Ion.getDefault(context).getHttpClient().getSSLSocketMiddleware();
sslMiddleWare.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
sslMiddleWare.setSSLContext(sslContext);

Ion.getDefault(context).getHttpClient().getSSLSocketMiddleware().setTrustManagers(trustAllCerts);
Ion.getDefault(context).getHttpClient().getSSLSocketMiddleware().setSSLContext(sslContext);

Ion.with(context).load("POST", serverUrl)
    .setHeader("Content-Type", "application/json")
    .setHeader("Accept", "application/json")
    .setLogging("ION_LOGGING", Log.VERBOSE).setJsonObjectBody(json)
于 2015-01-08T14:10:04.043 に答える