证书随机无法正确创建

时间:2012-05-27 07:29:25

标签: java android apache ssl-certificate

我创建了一个自定义httpclient,用于访问我的自定义信任存储区,并将其用于它尝试访问的所有ssl站点。这是代码:

public class MyHttpClient extends DefaultHttpClient {

    private Context context;

    public MyHttpClient(Context context) {

        this.context = context;
    }

    @Override
    protected ClientConnectionManager createClientConnectionManager() {

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory
                .getSocketFactory(), 80));
        registry.register(new Scheme("https", newSslSocketFactory(), 443));
        return new SingleClientConnManager(getParams(), registry);
    }

    private SSLSocketFactory newSslSocketFactory() {

        try {
            KeyStore trusted = KeyStore.getInstance("BKS");
            InputStream in = context.getResources().openRawResource(
                    R.raw.cacerts);
            try {
                trusted.load(in, "changeit".toCharArray());
            }
            catch (CertificateException c) {
                System.out
                        .println("There was a certificate exception in myhttpclient!");
            }
            finally {

                in.close();
            }
            return new SSLSocketFactory(trusted);
            }
            catch (Exception e) {
                throw new AssertionError(e);
            }
    }
}

这是它给我的堆栈跟踪:

W/System.err(4194): javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
W/System.err(4194):     at org.apache.harmony.xnet.provider.jsse.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:258)
W/System.err(4194):     at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:93)
W/System.err(4194):     at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:381)
W/System.err(4194):     at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:177)
W/System.err(4194):     at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
W/System.err(4194):     at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
W/System.err(4194):     at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:428)
W/System.err(4194):     at org.apache.http.impl.client.AbstractHttpClient$1.executeRequestSending(AbstractHttpClient.java:608)
W/System.err(4194):     at org.apache.http.impl.client.naf.redirect.NafRequestExecutorWrapperRedirectionHandler.executeRequestSendingUsual(NafRequestExecutorWrapperRedirectionHandler.java:96)
W/System.err(4194):     at org.apache.http.impl.client.naf.redirect.NafRequestExecutorWrapperRedirectionHandler.executeRequestSending(NafRequestExecutorWrapperRedirectionHandler.java:73)
W/System.err(4194):     at org.apache.http.impl.client.naf.auth.NafHttpAuthStrategyDefault.sendFirstRequest(NafHttpAuthStrategyDefault.java:487)
W/System.err(4194):     at org.apache.http.impl.client.naf.auth.NafHttpAuthStrategyDefault.performAuthExecutionUnsafe(NafHttpAuthStrategyDefault.java:388)
W/System.err(4194):     at org.apache.http.impl.client.naf.auth.NafHttpAuthStrategyDefault.performAuthExecution(NafHttpAuthStrategyDefault.java:200)
W/System.err(4194):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:556)
W/System.err(4194):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:505)
W/System.err(4194):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:483)
W/System.err(4194):     at com.wmmccreedy.vce.AgConnection.submitInfo(AgConnection.java:111)
W/System.err(4194):     at com.wmmccreedy.vce.LoginSubmitActvity$DownloadWebPageTask.doInBackground(LoginSubmitActvity.java:199)
W/System.err(4194):     at com.wmmccreedy.vce.LoginSubmitActvity$DownloadWebPageTask.doInBackground(LoginSubmitActvity.java:1)
W/System.err(4194):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
W/System.err(4194):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
W/System.err(4194):     at java.util.concurrent.FutureTask.run(FutureTask.java:138)
W/System.err(4194):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
W/System.err(4194):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
W/System.err(4194):     at java.lang.Thread.run(Thread.java:1019)

现在,这种方法正常工作......大约有50%的时间。我解决了#34;这通过创建一个while循环。它继续重新创建httpclient客户端并尝试一遍又一遍地访问服务器,直到它工作,通常只需要1到2次尝试(最多我看到的是4)。显然,这是非常低效的。

我已将问题缩小到上面发布的类,因为如果我只创建一次httpclient并尝试多次使用同一个类访问该网站,它将始终失败,或者总是成功,取决于我是否有一个好的' httpclient,或者“坏”' HttpClient的。 但是,如果我每次尝试访问网页时都会创建httpclient,它有时会工作,有时也无法正常工作。

那为什么要这样做,我该如何解决这个问题呢?为什么它只是间歇性地工作,客户的创造之间可能会发生什么变化呢?

编辑:解决了!

似乎我在我的信任库中留下了一些旧版本的一些别名,并且它随机选择了它首先找到的那个,这并不总是最终成为正确的。每个别名都包含所有相同的证书,但每个别名都具有不同顺序的所有证书。我进行了测试,直到找到了正确的商店,删除了其余部分,现在一切都很完美。

2 个答案:

答案 0 :(得分:2)

这不是“证书创建”问题。

服务器(对等方)没有向您发送证书。这可能是因为它无法在其信任库信任的人签名的密钥库中找到一个。

答案 1 :(得分:0)

这是Apache HTTP Client中的问题(在Android 2.3上观察到)。加载密钥库时,证书以随机顺序加载到内存数据结构中。 Apache HTTP Client中的PKIX路径验证逻辑有问题。它从服务器的证书开始并查看密钥库,如果查找的第一个证书是CA证书,则链成功构建并验证成功,但是,如果查找的第一个证书是服务器证书,则Apache HTTP客户端放弃并且验证失败。

因此,请确保您的密钥库中没有服务器和中间CA证书。