在Android的重写SSL信托经理(Overriding the SSL Trust Manage

2019-06-21 16:50发布

我试图重写信任管理器在Android中。 我要让底层的信任管理器中查看证书,但我需要确定一个证书已过期。 如果证书已过期,我需要忽略它,并接受证书。 一些移动设备将日期重置为旧日期,如果取出电池,造成该证书看起来好像它过期。 我的应用程序必须继续保持运行,即使出现这种情况。

我遇到的问题是,这行代码会抛出一个NullPointerException:

origTrustmanager.checkServerTrusted(certs, authType);

根据该文件,checkServerTrusted不应该抛出NullPointerExeption。 证书中有两个项目。 的authType设置为“RSA”。 如果我不实现自定义信任管理器中,将引发异常清晰地表示,该证书已过期,所以我知道底层的信托经理正在做的工作。 即使我设定的日期和时间,我的设备上的证书的有效期时间内,该checkServerTrusted线之上生成异常。 为什么? 显然,我做错了什么。 这里是我的自定义信任管理器以及如何,我访问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;
    }
  }
}    

代码访问网址:

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());

Answer 1:

如果你从来没有初始化origTrustmanager实例变量,这将有它的默认值null ,这的确会导致NPE任何你想使用它的时间。

我刚刚编辑我以前的答案在此展示的TrustManager初始化的一个例子。 (我还没有尝试在Android上,但它在普通的Java工作正常。)

要小心,不要碰到太多。 在这里,你在捕捉CertificateExceptionException在你的信任管理器:这是具有任何操作,因为这些方法是为了抛出那些异常的好。 确保你只能望尘莫及CertificateExpiredException如果你想忽略到期日期。

请注意,这仅仅是依赖于一个事实是,在实践中,证书验证的一般信任验证进行(在OpenJDK的实施至少)一招。 据我所知,没有什么在规格上,指出该证书过期之后验证。 据之前的信任要素的其他验证完成,你忽略了异常,你可以让通过比你想要更多的证书。



Answer 2:

使用此代码。这是为我工作

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)


文章来源: Overriding the SSL Trust Manager in Android
标签: android ssl