HttpClient SSLException
Posted
技术标签:
【中文标题】HttpClient SSLException【英文标题】: 【发布时间】:2014-11-06 00:39:32 【问题描述】:我尝试向 Web 服务发送 https 请求,但在几次成功尝试后,我开始不断收到此错误。这个错误是什么意思,为什么它会在第一次发生。
javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1884)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1842)
at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1825)
at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1751)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:127)
at org.apache.http.impl.io.AbstractSessionOutputBuffer.flushBuffer(AbstractSessionOutputBuffer.java:131)
at org.apache.http.impl.io.AbstractSessionOutputBuffer.flush(AbstractSessionOutputBuffer.java:138)
at org.apache.http.impl.io.ContentLengthOutputStream.flush(ContentLengthOutputStream.java:102)
at org.apache.http.entity.StringEntity.writeTo(StringEntity.java:94)
at org.apache.http.entity.HttpEntityWrapper.writeTo(HttpEntityWrapper.java:96)
at org.apache.http.impl.client.EntityEnclosingRequestWrapper$EntityWrapper.writeTo(EntityEnclosingRequestWrapper.java:108)
at org.apache.http.impl.entity.EntitySerializer.serialize(EntitySerializer.java:120)
at org.apache.http.impl.AbstractHttpClientConnection.sendRequestEntity(AbstractHttpClientConnection.java:263)
at org.apache.http.impl.conn.AbstractClientConnAdapter.sendRequestEntity(AbstractClientConnAdapter.java:227)
at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:255)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123)
at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:622)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:454)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:941)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:919)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:910)
at com.nim.service.push.exacttarget.ExactTargetPushService.sendMessageContacts(ExactTargetPushService.java:208)
at com.nim.service.push.exacttarget.ExactTargetPushService.sendPushNotification(ExactTargetPushService.java:106)
at com.nim.domain.push.PushManager.pushHelper(PushManager.java:91)
at com.nim.domain.push.PushManager.pushEntitlementChange(PushManager.java:40)
at com.nim.domain.push.PushManager.pushEntitlementChange(PushManager.java:36)
at com.nim.domain.push.PushManager.pushEntitlementChange(PushManager.java:51)
at com.nim.batch.entitlement.SubscriptionEntitlementWriter.pushClientNotifications(SubscriptionEntitlementWriter.java:161)
at com.nim.batch.entitlement.SubscriptionEntitlementReader.retrievePage(SubscriptionEntitlementReader.java:71)
at com.nim.batch.entitlement.SubscriptionEntitlementReader.retrievePage(SubscriptionEntitlementReader.java:1)
at com.nim.batch.entitlement.EntitlementPagedDifferentialReader.read(EntitlementPagedDifferentialReader.java:96)
at sun.reflect.GeneratedMethodAccessor96.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy77.read(Unknown Source)
at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:90)
at org.springframework.batch.core.step.item.FaultTolerantChunkProvider.read(FaultTolerantChunkProvider.java:87)
at org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:108)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:367)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:214)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:143)
at org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:103)
at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:68)
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:386)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:264)
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:76)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:367)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:214)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:143)
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:250)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:135)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:61)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:281)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.RuntimeException: Could not generate DH keypair
at sun.security.ssl.ECDHCrypt.<init>(ECDHCrypt.java:80)
at sun.security.ssl.ClientHandshaker.serverKeyExchange(ClientHandshaker.java:692)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:274)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:878)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:814)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:702)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122)
... 64 more
Caused by: java.security.InvalidAlgorithmParameterException: parameter object not a ECParameterSpec
at org.bouncycastle.jce.provider.JDKKeyPairGenerator$EC.initialize(Unknown Source)
at sun.security.ssl.ECDHCrypt.<init>(ECDHCrypt.java:75)
... 72 more
【问题讨论】:
ECDH(椭圆曲线 Diffie-Hellman)密钥对生成的支持类中似乎缺少某些内容。不能说更多了。 【参考方案1】:我遇到了同样的问题。这篇文章帮助了我:http://iwang.github.io/support/2014/03/14/cxf-cause-https-error.html
本质上,问题在于您使用的是 Bouncy Castle JDK1.4 库,而不是更新的 1.5 库。
为了解决这个问题,我完全移除了 Bouncy Castle。我发现它是被一个不相关的库拉进来的,所以我在 pom.xml 文件的依赖项中添加了以下内容:
<exclusions>
<exclusion>
<groupId>bouncycastle</groupId>
<artifactId>bcmail-jdk14</artifactId>
</exclusion>
<exclusion>
<groupId>bouncycastle</groupId>
<artifactId>bcprov-jdk14</artifactId>
</exclusion>
<exclusion>
<groupId>bouncycastle</groupId>
<artifactId>bctsp-jdk14</artifactId>
</exclusion>
<exclusions>
如果不能删除,建议更新到 jdk15 库。
链接文章的解释:
Java 1.5 对椭圆曲线加密 API 进行了更改。 如果您使用 Java Cryptography Extension (JCE) >provider 用于 Java 1.4 或更早版本将不支持此新的 API 更改,并且 使用 SSL 时,基于 Diffie-Hellman 的密码可能会出错。这 SSL 实现尝试设置椭圆曲线加密 使用 ECGenParameterSpec 对象。这个对象直到 Java 1.5 才被添加: http://docs.oracle.com/javase/7/docs/api/java/security/spec/ECGenParameterSpec.html (注意从行)。
例如,bcprov-jdk14-131-1.0.jar 是 Bouncy Castle,它是 一个这样的供应商。此版本的提供程序适用于 JDK 1.4. Bouncy Castle 为每个 JDK 级别提供不同的库。
【讨论】:
谢谢。我正在确认此修复程序。你知道罪魁祸首究竟是哪个 bouncycastle 库吗?是 bcprov-jdk14、bctsp-jdk14 还是 bcmail-jdk14? 据我所知,所有这些。它们只是我的依赖引入的库。我使用 Eclipse 中的 Dependency Hierarchy 视图来计算出有问题的库(在我的例子中是 iText)。【参考方案2】:我有一段时间遇到过这个问题..从升级后我让它工作正常
bcprov-jdk14
转bcprov-jdk15
【讨论】:
谢谢!它也对我有用..我从java2s.com/Code/Jar/b/Downloadbcprovjdk15146jar.htm下载它【参考方案3】:我遇到了这个问题并且无法使用 BC15,因为我们仍然为一些 1.4 客户端(旧的 unix OS 客户端)提供旧版支持。鉴于此限制,我能够通过在包 java.security.spec 中包含 ECGenParameterSpec.java 类来解决该问题。不要从 1.5 源代码中复制 Java 版本;它拥有甲骨文的版权。这是一个获得 Apache 许可的示例实现。如您所见,该类并不是非常复杂,我相信您可以自己编写。
https://android.googlesource.com/platform/libcore/+/a47f800/luni/src/main/java/java/security/spec/ECGenParameterSpec.java
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.security.spec;
/**
* The parameter specification used to generate elliptic curve domain parameters.
*/
public class ECGenParameterSpec implements AlgorithmParameterSpec
// Standard (or predefined) name for EC domain
// parameters to be generated
private final String name;
/**
* Creates a new @code ECGenParameterSpec with the specified standard or
* predefined name of the to-be-generated domain parameter.
*
* @param name
* the name of the elliptic curve domain parameter.
*/
public ECGenParameterSpec(String name)
this.name = name;
if (this.name == null)
throw new NullPointerException();
/**
* Returns the name (standard or predefined) of the to-be-generated elliptic
* curve domain parameter.
*
* @return the name
*/
public String getName()
return name;
在您的项目源中包含此文件(如果需要,从 proguard 等中排除),并且您已设置好(至少针对此错误)。
【讨论】:
【参考方案4】:即使我遇到了同样的问题,但在我的应用程序中,我不允许升级赏金城堡罐子。
问题: 我们有一个使用 google api 进行谷歌翻译的通用 API,该 API 用于向谷歌 API 发出 https 请求,因为赏金城堡也被注册为 JCE 提供者之一并用于加密,我们曾经得到确切的错误。
我在没有升级赏金城堡罐子的情况下通过几个步骤解决了这个问题。 在进行 https 调用之前,我所做的是从安全提供者列表中删除赏金城堡并进行了 https 调用,以便使用 Sun 的 JCE 提供者进行加密。这对我来说效果很好。 通过下面的代码在运行时从服务提供者列表中删除赏金城堡,在删除它之前,我获取了赏金城堡提供者实例并在 https 调用完成后再次添加它。
代码如下
java.security.Provider provider = java.security.Security.getProvider(BouncyCastleProvider.PROVIDER_NAME);
java.security.Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
int index = getProviderIndex(BouncyCastleProvider.PROVIDER_NAME);
String url = "some https url";
org.apache.commons.httpclient.methods.GetMethod method = new org.apache.commons.httpclient.methods.GetMethod(url);
int responseCode = HTTP_CLIENT.executeMethod(method);
if(provider != null && index >= 0)
java.security.Security.insertProviderAt(provider, (index+1));
private int getProviderIndex(String name)
final Provider[] providers = Security.getProviders();
/**
* Just to log available providers
*/
for (int i = 0; i < providers.length; i++)
Provider provider = providers[i];
LOGGER.error(provider.getName() + " " + provider.getVersion() + ": " + provider.getInfo());
for(int index = 0; index < providers.length; index++)
if (providers[index] != null && providers[index].getName() != null
&& providers[index].getName().equalsIgnoreCase(name))
return index;
return -1;
【讨论】:
【参考方案5】:添加这个
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.54</version>
</dependency>
【讨论】:
请详细说明这一点,以便我们大家更容易理解关键点。以上是关于HttpClient SSLException的主要内容,如果未能解决你的问题,请参考以下文章
轻松把玩HttpClient之封装HttpClient工具类,插件式配置HttpClient对象