ColdFusion CFHTTP I/O异常:对等体未经认证 - 即使已将证书添加到密钥库

7
我目前正在与一个支付处理器合作。我可以从我们的服务器浏览到付款网址,因此这不是防火墙问题,但当我尝试使用CFHTTP时,我会得到一个I/O异常:对等体未经身份验证。我已将他们最新的安全证书下载并安装到cacerts密钥库中,并重新启动了CF,仍然出现相同的错误。我不仅安装了提供者证书,还安装了证书链中的另外两个Verisign证书颁发机构证书。该证书是较新的3级扩展验证证书之一。
有人遇到过这种情况并找到解决方案吗?

2
虽然回应晚了,但我最终选择了在http://www.cftagstore.com/tags/cfxhttp5.cfm找到的CFX_HTTP5自定义标签。 - Barry Jordan
8个回答

9
我的一个同事在连接到第三方时遇到了相同的问题,他找到了以下解决方法。

http://www.coldfusionjedi.com/index.cfm/2011/1/12/Diagnosing-a-CFHTTP-issue--peer-not-authenticated

https://www.raymondcamden.com/2011/01/12/Diagnosing-a-CFHTTP-issue-peer-not-authenticated/

我们使用了Pete Freitag在页面下方提供的解决方案。它是有效的,但我认为应该谨慎使用,因为它涉及动态删除和添加JsafeJCE提供程序的特定属性。
为了档案保存,这里是Pete Freitag评论的原始内容:

I've narrowed this down a bit further, and removing the KeyAgreement.DiffieHellman from the RSA JsafeJCE provider (which causes the default sun implementation to be used instead) seams to work, and probably has less of an effect on your server than removing the entire provider would. Here's how you do it:

<cfset objSecurity = createObject("java", "java.security.Security") />
<cfset storeProvider = objSecurity.getProvider("JsafeJCE") />
<cfset dhKeyAgreement = storeProvider.getProperty("KeyAgreement.DiffieHellman")>
<!--- dhKeyAgreement=com.rsa.jsafe.provider.JSA_DHKeyAgree --->
<cfset storeProvider.remove("KeyAgreement.DiffieHellman")>

Do your http call, but pack the key agreement if you want:

<cfset storeProvider.put("KeyAgreement.DiffieHellman", dhKeyAgreement)>

I figured this out by using the SSLSocketFactory to create a https connection, which provided a bit more details in the stack trace, than when using cfhttp:

yadayadayada Caused by: java.security.InvalidKeyException: Cannot
build a secret key of algorithm TlsPremasterSecret at
com.rsa.jsafe.provider.JS_KeyAgree.engineGenerateSecret(Unknown
Source) at javax.crypto.KeyAgreement.generateSecret(DashoA13*..) at
com.sun.net.ssl.internal.ssl.DHCrypt.getAgreedSecret(DHCrypt.java:166)

Would be great if the exception thrown from ColdFusion was a bit less generic.


1
嘿,巴里,有点困惑。你在这里说你使用了Pete Freitag建议的解决方法,但在上面的评论中你说你最终选择了CFX_HTTP5自定义标签。那么你最终采用的是哪种解决方案? - Brian FitzGerald

4

针对使用现代ssl密码的web服务器的coldfusion 8特定问题:

我使用JDK 1.6.45上的coldfusion 8,并且在使用<cfdocument ...>时遇到了仅显示红叉而不是图像的问题,同时cfhttp也无法连接到带有ssl的本地web服务器。

我的测试脚本以重现coldfusion 8问题为目标。

<CFHTTP URL="https://www.onlineumfragen.com" METHOD="get" ></CFHTTP>
<CFDUMP VAR="#CFHTTP#">

这给了我一个相当通用的错误:“I/O异常:对等方未经身份验证。” 然后我尝试将服务器证书(包括根和中间证书)添加到Java密钥库和ColdFusion密钥库中,但没有起作用。 然后我使用调试工具排查问题。

java SSLPoke www.onlineumfragen.com 443

并获得

javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair

并且

Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be
multiple of 64, and can only range from 512 to 1024 (inclusive)
    at com.sun.crypto.provider.DHKeyPairGenerator.initialize(DashoA13*..)
    at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:627)
    at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:107)
    ... 10 more

我有一个想法,即网络服务器(在我这种情况下是apache)使用非常现代的ssl密码并且很严格(qualys得分a+)并使用比1024位更强的Diffie-Hellman组。显然,coldfusion和java jdk 1.6.45无法管理此类密码。 在这个过程中的下一步是考虑为Java安装替代安全提供程序,并选择了bouncy castle。 详见http://www.itcsolutions.eu/2011/08/22/how-to-use-bouncy-castle-cryptographic-api-in-netbeans-or-eclipse-for-java-jse-projects/ 然后我下载了
bcprov-ext-jdk15on-156.jar

http://www.bouncycastle.org/latest_releases.html下载最新版本的BC(Bouncy Castle)并将其安装在C:\jdk6_45\jre\lib\ext或您的JDK所在位置,如果是ColdFusion 8的原始安装,则应该位于C:\JRun4\jre\lib\ext下,但我使用了一个更新的JDK(1.6.45),它位于ColdFusion目录之外。将bcprov-ext-jdk15on-156.jar放入\ext目录非常重要(这为我节省了大约两个小时和一些头发;-)然后我使用wordpad编辑了文件C:\jdk6_45\jre\lib\security\java.security(而不是editor.exe!)并为新提供程序添加了一行。之后,列表看起来像:

#
# List of providers and their preference orders (see above):
#
security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider
security.provider.2=sun.security.provider.Sun
security.provider.3=sun.security.rsa.SunRsaSign
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC
security.provider.10=sun.security.mscapi.SunMSCAPI

(请查看新的1号位置)

然后完全重新启动ColdFusion服务。 接下来您可以:

java SSLPoke www.onlineumfragen.com 443 (or of course your url!)

享受这种感觉...当然,<cfhttp 和 <cfdocument 像以前一样完美地运行,直到我们在 Apache 中加固了 SSL 密码!

真是一个不眠之夜和漫长的一天。希望这能对某个人(部分或全部)有所帮助。如果您有问题,请发送电子邮件至 info ...(上面的域名)。


这真的非常有帮助,但我发现如果我把BouncyCastle放在位置1,ColdFusion 8服务无法启动。但是在位置2(sun.security.provider.Sun之后)它可以正常工作。再次感谢您节省了我大量的时间! - lunadesign

3

您确定将其添加到了正确的密钥库中吗?请记住ColdFusion使用自己的Java实例。我曾经花费了几个小时才想起这一点。您需要的是位于类似于/ColdFusion8/runtime/jre/lib/security/的位置。


嗨Ryber,这就是我添加它们的地方。我之前添加了其他的,一直都有效。谢谢。 - Barry Jordan
也许你缺少了证书链中的某个证书,Java会抱怨无法验证签名者的真实性? - Sixten Otto
嗨 Sixteen Otto,我已经安装了链中的所有三个证书,仍然不起作用! - Barry Jordan

2

在CMD中尝试以下操作:

C:\ColdFusion9\runtime\jre\bin> keytool -import -keystore ../lib/security/cacerts -alias uniquename -file certificatename.cer

注意:我们必须选择安全文件夹中存在的正确密钥库,因为在bin文件夹中还有其他密钥库文件。如果我们将证书导入到这些密钥库中,它将无法正常工作。


0

我正在使用JRun。在尝试了许多不同的方法之后,我找到了一些适用于我的设置的信息片段。我配置了一个(1)HTTPS SSLService和自己的truststore文件。这导致以下链接中的信息变得重要。

http://helpx.adobe.com/coldfusion/kb/import-certificates-certificate-stores-coldfusion.html

注意:如果您正在使用JRun作为基础的J2EE服务器(无论是Server Configuration还是Multiserver/J2EE with JRun Configuration),并且已经为内部JRun Web服务器(JWS)启用了SSL,则需要将证书导入到安全JWS的jrun.xml文件中定义的信任存储库中,而不是JRE密钥库。默认情况下,该文件称为“trustStore”,通常位于Multiserver/J2EE with JRun配置的jrun_root/lib或ColdFusion Server配置的cf_root/runtime/lib下。您可以使用相同的Java keytool来管理trustStore。

这是我jrun.xml文件的摘录:

<service class="jrun.servlet.http.SSLService" name="SSLService">
  <attribute name="port">8301</attribute>
  <attribute name="keyStore">/app/jrun4/cert/cfusion.jks</attribute>
  <attribute name="trustStore">/app/jrun4/cert/truststore.jks</attribute>
  <attribute name="name">SSLService</attribute>
  <attribute name="bindAddress">*</attribute>
  <attribute name="socketFactoryName">jrun.servlet.http.JRunSSLServerSocketFactory</attribute>
  <attribute name="interface">*</attribute>
  <attribute name="keyStorePassword">cfadmin</attribute>
  <attribute name="deactivated">false</attribute>
</service>

我将证书导入到这个信任存储 (/app/jrun4/cert/truststore.jks) 后,重新启动 ColdFusion 后它就可以工作了。


(1) http://helpx.adobe.com/legacy/kb/ssl-jrun-web-server-connector.html

(1){{link1:http://helpx.adobe.com/legacy/kb/ssl-jrun-web-server-connector.html}}

0

我刚刚发现的是在这篇文章中提到的:http://kb2.adobe.com/cps/400/kb400977.html,经过了很多挖掘后,在其他几个地方也有提到。

如果你正在查看这篇文章,你很可能已经将你的“server.crt”证书插入到了正确的根位置,并且你可能已经使用以下命令将其插入到了位于/ColdFusion9/runtime/jre/lib/security的cacerts文件中:

\ColdFusion9\runtime\jre\bin\keytool -import -v -alias someServer-cert -file someServerCertFile.crt -keystore cacerts -storepass changeit

(如果你还没有这样做,请立即执行)。我遇到的问题是,我正在本地主机上设置ssl,所以在执行这些步骤后,我仍然得到了相同的错误。

事实证明,你还需要将你的“server.crt”插入到位于/ColdFusion9/runtime/jre/lib的“trustStore”文件中,使用以下命令:

\ColdFusion9\runtime\jre\bin\keytool -import -v -alias someServer-cert -file someServerCertFile.cer -keystore trustStore -storepass changeit

希望这能为某人节省时间。


0

将证书添加到密钥库对我在CF9 Enterprise上不起作用。

最终使用了CFX标签,CFX_HTTP5


0

我知道这是一个非常古老的讨论,但由于在搜索“peer not authenticated”错误时它仍然出现在前面,我想分享一下对于大多数人来说,简单的解决方案是更新CF使用的JVM。(稍后会详细介绍如何操作。)

问题的原因通常是被调用的服务已经进行了更改,需要较新版本的TLS或SSL(以及可能需要更改支持的算法)。较新的JVM提供了这个功能,而早期的版本则没有。由于CF运行在JVM之上,因此从CF中发出的调用(例如cfhttp、cfldap、cfmail等)会“突然”开始失败。

当然,有时候证书更新是答案(即使在这种情况下,您也必须小心谨慎),但并不总是需要的。更新JVM还可以提供其他好处,例如修复错误等。

唯一的挑战是知道您的CF版本支持哪个JVM。(但即使是仍在运行旧版CF的用户也发现,更新CF使用的JVM可以解决此问题,并且不会引起任何其他问题。)

我在2019年的帖子中讨论了所有这些内容:

https://coldfusion.adobe.com/2019/06/error-calling-cf-via-https-solved-updating-jvm/

希望能够帮助到某些人。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接