初始化默认 SSL 上下文失败

Posted

技术标签:

【中文标题】初始化默认 SSL 上下文失败【英文标题】:Failure initializing default SSL context 【发布时间】:2012-04-08 15:15:57 【问题描述】:

我的httpclient项目遇到了一个奇怪的问题。它在其他两个使用java1.6的Centos系统上运行成功。但它在另一台机器(centos 和 java1.6)上失败了。问题是:

java.lang.IllegalStateException: [java] 在 org.apache.http.conn.ssl.SSLSocketFactory.createDefaultSSLContext(SSLSocketFactory.java:211) [java] 在 org.apache.http.conn.ssl.SSLSocketFactory.(SSLSocketFactory.java:333) [java] 在 org.apache.http.conn.ssl.SSLSocketFactory.getSocketFactory(SSLSocketFactory.java:165) [java] 在 org.apache.http.impl.conn.SchemeRegistryFactory.createDefault(SchemeRegistryFactory.java:45) [java] 在 org.apache.http.impl.client.AbstractHttpClient.createClientConnectionManager(AbstractHttpClient.java:294) [java] 在 org.apache.http.impl.client.AbstractHttpClient.getConnectionManager(AbstractHttpClient.java:445) [java] at simulativeLogin.WebClientDevWrapper.wrapClient(Unknown Source) [java] at simulativeLogin.GetAccessToken.getToken(Unknown Source) [java] 在 crawler.FriendshipCrawler.main(未知来源) [java] 在 java.lang.reflect.Method.invoke(libgcj.so.10) [java] 在 org.apache.tools.ant.taskdefs.ExecuteJava.run(ant-1.7.1.jar.so) [java] 在 org.apache.tools.ant.taskdefs.ExecuteJava.execute(ant-1.7.1.jar.so) [java] 在 org.apache.tools.ant.taskdefs.Java.run(ant-1.7.1.jar.so) [java] 在 org.apache.tools.ant.taskdefs.Java.executeJava(ant-1.7.1.jar.so) [java] 在 org.apache.tools.ant.taskdefs.Java.executeJava(ant-1.7.1.jar.so) [java] 在 org.apache.tools.ant.taskdefs.Java.execute(ant-1.7.1.jar.so) [java] 在 org.apache.tools.ant.UnknownElement.execute(ant-1.7.1.jar.so) [java] 在 java.lang.reflect.Method.invoke(libgcj.so.10) [java] 在 org.apache.tools.ant.dispatch.DispatchUtils.execute(ant-1.7.1.jar.so) [java] 在 org.apache.tools.ant.Task.perform(ant-1.7.1.jar.so) [java] 在 org.apache.tools.ant.Target.execute(ant-1.7.1.jar.so) [java] 在 org.apache.tools.ant.Target.performTasks(ant-1.7.1.jar.so) [java] 在 org.apache.tools.ant.Project.executeSortedTargets(ant-1.7.1.jar.so) [java] 在 org.apache.tools.ant.Project.executeTarget(ant-1.7.1.jar.so) [java] 在 org.apache.tools.ant.helper.DefaultExecutor.executeTargets(ant-1.7.1.jar.so) [java] 在 org.apache.tools.ant.Project.executeTargets(ant-1.7.1.jar.so) [java] 在 org.apache.tools.ant.Main.runBuild(ant-1.7.1.jar.so) [java] 在 org.apache.tools.ant.Main.startAnt(ant-1.7.1.jar.so) [java] 在 org.apache.tools.ant.launch.Launcher.run(ant-launcher-1.7.1.jar.so) [java] 在 org.apache.tools.ant.launch.Launcher.main(ant-launcher-1.7.1.jar.so) [java] 引起:java.lang.IllegalStateException [java] 在 gnu.javax.net.ssl.provider.X509KeyManagerFactory.engineGetKeyManagers(libgcj.so.10) [java] 在 javax.net.ssl.KeyManagerFactory.getKeyManagers(libgcj.so.10) [java] 在 org.apache.http.conn.ssl.SSLSocketFactory.createSSLContext(SSLSocketFactory.java:187) [java] 在 org.apache.http.conn.ssl.SSLSocketFactory.createDefaultSSLContext(SSLSocketFactory.java:209)

【问题讨论】:

这是线索:由IllegalStateException gnu.javax.net.ssl.provider.X509KeyManagerFactory.engineGetKeyManagers in libgcj.so.10 引起。 对于我自己,我只是想“gcj?你的问题就在那里!”但我想这对你来说不是一个有用的答案…… 问题已解决。 javac 的版本是 1.5,但 open-jdk 的版本是 1.6。匹配版本后问题消失。 @DonalFellows,你应该为此写一个答案。 Lujingsun,这不仅仅是 Java 的版本,还有 JRE 实现及其安全提供程序,特别是您明显使用的是 GCJ 实现,而不是 OpenJDK。 【参考方案1】:

这不是你的错。使用另一个JVM,这将解决您的问题。我有同样的问题。我在 Gumstix/linux/jamVM 上运行 Apache HttpClient。我得到了完全相同的例外。这是X509的测试程序。我在我的 Mac mini 上运行它,结果是“SunX509”作为算法;但在 jamVM 上,它是“空的”。试试看。

public class TestX509 
    public static void main(String[] args) 
        String algorithm = Security
            .getProperty("ssl.KeyManagerFactory.algorithm");

        System.out.println("algorithm is " + algorithm);
    

参见 gnu.javax.net.ssl.provider.X509KeyManagerFactory.java 第 108 行的源代码。这就是异常的来源。 (因为 'current' 是一个密钥管理器,它是空的。你从前面的测试中知道。)

104:   protected KeyManager[] engineGetKeyManagers()
105:   
106:     if (current == null)
107:       
108:         throw new IllegalStateException();
109:       
110:     return new KeyManager[]  current ;
111:   
112:

由于库抛出IllegalStateException,这是一个RuntimeException,有人认为这是GCJ的一个错误,并在此报告http://code.google.com/p/selenium/issues/detail?id=2483。

【讨论】:

【参考方案2】:

我看到您使用 GCJ 作为 Java 的实现(因为原因异常源自 gnu.javax.net.ssl.provider.X509KeyManagerFactory 类,以及许多堆栈级别在 libgcj.so.10 中的方式)。不幸的是,这不是官方认可的 Java 版本。它在其实施的几个方面存在许多问题,有时可能会非常棘手。特别是 X.509 密钥处理似乎有问题! (我不知道它确实如此,但它显然如此。)

最简单的解决方法是切换到使用不同的 Java 实现。 Sun/Oracle Java 实现绝对不错(我广泛使用它),而且我也听说过有关 OpenJDK 实现的好消息;据我了解,OpenJDK 是删除了某些部分的 Sun JDK(特别是他们从其他地方获得许可的位,我 相信 是编解码器和 GUI 代码的一部分,但我不肯定知道)。您不想做的是花时间解决没有人推荐使用的 Java 实现中的错误!

【讨论】:

我也不知道gcj实现了1.6的API;我会更加多疑……【参考方案3】:

答案就在 cmets 中。如果您确实输入了java -version 并看到java version "1.5.0",则需要确保您使用的是Java 6。它应该是java version "1.6.0"

【讨论】:

以上是关于初始化默认 SSL 上下文失败的主要内容,如果未能解决你的问题,请参考以下文章

重新定义默认 SSL 上下文时找不到 Java 密钥库

上下文初始化失败 Spring

ContextLoader:上下文初始化失败

Tomcat - 上下文初始化失败

由于已经存在根应用程序上下文,无法初始化上下文,因此在 tomcat 中部署战争失败

上下文初始化失败:org.springframework.beans.factory.BeanDefinitionStoreException