CFHTTP 无法找到请求目标的有效认证路径

3

我想从一个网站上爬取数据,其他https网站都可以使用,但这个网站上次还可以用,现在失败了。

<cfhttp url="https://www.cliftoncameras.co.uk/all-brands-and-types-of-used-cameras/"></cfhttp>

如果我运行cfhttp的转储:

异常:PKIX路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到所请求目标的有效认证路径

我尝试使用最新的JRE版本12运行,没有变化https://helpx.adobe.com/coldfusion/kb/import-certificates-certificate-stores-coldfusion.html 返回CF原始JRE,下载目标SSL证书并使用keytool安装,没有变化

c:\ColdFusion2018\jre\bin\keytool -import -keystore cacerts -alias cliftoncameras -file c:\ColdFusion2018\jre\lib\security\cliftoncameras.cer

我将CFAdmin中的websocket更改为代理 - 没有变化 每次都重新启动了CF应用程序服务器。
还有什么可以做的吗?

当您更新JRE时,是否将证书导入到正确的密钥库文件中?它不再是ColdFusion附带的默认位置,就像您的示例所示。 - Miguel-F
我尝试过两个,根据使用情况一个一个地尝试。谢谢。 - Daniel Cook
假设您可以访问jvm.config设置,请备份该文件。然后修改它以启用调试,即添加“-Djavax.net.debug = all”并重新启动CF。https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/ReadDebug.html - SOS
上周这个还能用,这周怎么了?是更新了吗?还是改了代码? - SOS
3个回答

4

在我的开发平台上,我添加了

-Dcom.sun.security.enableAIAcaIssuers=true

在 ColdFusion2018\cfusion\bin\jvm.config 文件的 java.args 中进行设置。

然后重新启动 CF 应用服务器,现在我的 CFHTTP 调用成功了。

感谢 @agreax 提供的解决方案。

感谢 @sevroberts 的答案,虽然我无法使其正常工作。生产主机已将 SSL 证书安装到密钥库中并通过这种方式成功解决。他们说:

如果您使用 FireFox 浏览器并在浏览您想让 cfhttp 请求访问的 URL 时单击锁定图标,您就可以获取更多信息并单击查看证书选项。 您需要下载 PEM(证书),而不是 Chain。下载后,您需要运行 keytool 将其导入到 keystore 中。

如果您在 ColdFusion 的 JVM 中使用默认 JRE,则需要向开发计算机安装 JDK。 您可以查看我们在维基上列出的有关从命令提示符导入 SSL 到存储区的详细信息和步骤。 https://wiki.hostek.com/ColdFusion_Tips_%26_Tricks#Fixing_cfhttp_Connection_Failures_with_Keytool

感谢 @alexbaban 提供的解决方法,虽然它有效,但由于需要使用标签 cfexecute,我无法实现。


那么主机通过安装证书解决了它? - SOS
这就是他们说的,然而我在与另一个供应商有另一个CFHTTP问题 - 在将他们的SSL证书安装到DEV上的密钥库后,问题得到了解决!甚至在生产环境中都没有出现问题。不一致的问题真是让人头疼。 - Daniel Cook
编辑 - 哎呀...不一致的结果真是让人头疼。你使用的配置和生产环境一样吗?ColdFusion或JVM的差异可能会解释这个问题。 - SOS

3
我以前在加载正常的网站时看到过来自Java和Coldfusion的java.security.cert.CertPathBuilderException错误,但是即使将证书添加到CF密钥库并重新启动后也会导致cfhttp出现错误。
在目标网站服务器证书配置存在信任链问题时会发生这种情况——当一个或多个信任链路径需要浏览器执行“额外下载”证书时。这可能是因为单个信任链路径中缺少中间证书,或者因为信任链中有多个分支具有不同的指纹,并且来自一个或多个分支的一个或多个证书未被提供。
如果您通过诸如ssllabs.com这样的SSL分析工具对目标网站进行分析(例如https://globalsign.ssllabs.com/analyze.html?d=www.cliftoncameras.co.uk&hideResults=on),则会发现他们的中间证书Starfield Secure Certificate Authority - G2没有被服务器提供,这迫使客户端执行“额外下载”操作。对于大多数正式的浏览器,这不会是问题,但是由cfhttp使用的Java客户端需要服务器直接提供几乎所有中间和根证书。直到几年前,大多数移动操作系统也是如此。
因此,理想的解决方案是联系Cliftoncameras,并要求他们的服务器管理员安装正确的Starfield Intermediate证书以便正常提供。
你可以通过将Starfield Secure Certificate Authority - G2中间证书安装在CF密钥库中作为可能的解决方法。

谢谢,我对Clifton Cameras的做法没有什么发言权,所以我会尝试添加中间证书。 - Daniel Cook
我安装了许多Starfield证书,包括SSL分析器中的证书 - 但没有任何改变。 - Daniel Cook
1
Daniel Cook - 有趣的是,cfhttp调用在trycf.com上可以使用,但只能使用Lucee 5。我无法弄清原因。我尝试安装“Starfield Secure...”证书和cliftoncameras证书,但仍然没有成功。毫无疑问,我错过了什么,但不确定是什么......无论如何,此线程提到了一个JVM参数,对我有帮助:-Dcom.sun.security.enableAIAcaIssuers=true。步骤1)备份jvm.config文件(别忘了这样做)2)添加-Dcom.sun.security.enableAIAcaIssuers=true参数3)重新启动CF服务器。 - SOS
1
同意,就是这样!非常感谢,我只需要看看能否说服主机在实际服务器上进行更改! - Daniel Cook
生产主机已将SSL证书添加到密钥库中,并且现在也在生产环境中运行。我已经要求他们提供有关所添加的SSL证书的更多信息。 - Daniel Cook
显示剩余3条评论

1
如果您无法使密钥库正常工作,也许您想尝试这个方法。
创建一个专用的命令行可执行文件(.exe),它将读取网页并将源代码保存到文本文件中。然后您可以使用ColdFusion来读取该文件并处理数据。
以下是ColdFusion代码:
<cfscript>

    _execPath = "c:/bin/clifton.exe";
    _filePath = "c:/bin/clifton.txt";

    // run your command-line app (clifton.exe)
    cfexecute(name="#_execPath#");  

    // wait for the file
    do {
        sleep(100);
    } while ( not fileExists(_filePath) ) 

    // wait for write to finish
    do {
        sleep(100);
        _fileInfo = getFileInfo(_filePath);
        writeOutput(" ## ");
        cfflush();
    } while ( _fileInfo.size eq 0 || dateDiff("s", _fileInfo.lastmodified, now()) lte 3 )

    writeOutput("<hr />")

    _result = fileRead(_filePath);
    writeDump(_result);

</cfscript>


正如您所看到的,它依赖于clifton.exe并读取clifton.txt(执行clifton.exe的结果为clifton.txt)。


如何制作clifton.exe

您将使用Dart SDK和dart2native工具在开发计算机上创建可执行文件。您可以将可执行文件部署到生产服务器作为独立应用(无需在生产环境中安装Dart SDK)。

// clifton.dart

import 'dart:convert';
import 'dart:io';

main() {
  //
  const String _certFilePath = 'c:/bin/sfig2.crt.pem';
  const String _responseFilePath = 'c:/bin/clifton.txt';
  const String _uri =
      'https://www.cliftoncameras.co.uk/all-brands-and-types-of-used-cameras/';

  final File _file = new File(_responseFilePath);
  final IOSink _sink = _file.openWrite();

  final SecurityContext _context = new SecurityContext();
  _context.setTrustedCertificates(_certFilePath);

  final HttpClient _client = new HttpClient(context: _context);
  saveSourceToFile(_client, _uri, _sink);
  _client.close();
  //
}

// get web page source then write it to file
void saveSourceToFile(HttpClient _client, String _uri, IOSink _sink) {
  //
  _client
      .getUrl(Uri.parse(_uri))
      .then((req) => req.close())
      .then((res) => res.transform(Utf8Decoder()).listen((data) {
            // as data is received write to file
            _sink.write(data);
          }, onDone: () {
            _sink.close();
          }));
  //
}
  • https://dart.dev/下载并安装Dart SDK
  • 打开终端窗口,使用dart --version测试Dart的安装情况(如果需要,在任何文件夹中都应该能够运行dart,将dart添加到您的PATH中)
  • 在终端窗口中,使用cd c:\bin更改目录到c:\bin
  • 接下来,运行dart2native clifton.dart -o clifton.exe
  • 如果编译成功,您应该在c:\bin中拥有三个文件:clifton.dartclifton.exe和证书sfig2.crt.pem
  • 如果您希望,可以在终端窗口中测试运行clifton.exe,它应该会创建clifton.txt文件
  • 测试调用clifton.exe并等待clifton.txt输出内容的ColdFusion页面
如果您要在生产环境中部署,您需要同时使用文件 clifton.exesfig2.crt.pem(证书)。

祝你好运!


谢谢,我很感激你提供的详细建议。在尝试这样一个相当大的解决方案之前,我认为现在是时候联系零售商解决这个问题了。 - Daniel Cook
不客气。它已经过测试,即使您需要安装Dart,也可以在不到半小时的时间内完成所有操作。 - Alex Baban
好的,那我差不多被说服了!我需要提取多个URL,因此需要一个URL数组/导出文件,并使用循环创建它们。我会考虑修改您提供的代码。 - Daniel Cook
没错。如果你遇到问题可以告诉我。你可以多次调用 saveSourceToFile(_client, _uri, _sink); 方法。你可以保持相同的 _client,只需传递不同的 _uri_sink 参数即可。由于每个调用都是异步的,所以你可能需要使用递归。 - Alex Baban
虽然它能工作!谢谢。我意识到cfexecute无法运行,并且快速的互联网搜索提醒了我为什么。共享生产主机提供商也不想启用它。https://wiki.hostek.com/ColdFusion_FAQs#Can_I_use_CFExecute.3F - Daniel Cook

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