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

CFHTTP unable to find valid certification path to requested target

我正在寻找从网站上抓取数据的方法,其他 https 网站可以正常工作,上周还可以,但现在失败了

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

如果我 运行 cfhttp

转储

Exception: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

我已经尝试了 运行 最新的 JRE 版本 12 - 没有变化

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

恢复为 CF 原始 JRE,下载目标 SSL 证书并使用密钥工具安装它 - 无变化

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

我将 CFAdmin 中的 websocket 更改为代理 - 无变化

我确实每次都重新启动了 CF 应用程序服务器。

我还能做什么?

我之前也曾在 Java 和 Coldfusion 网站上看到过这个 java.security.cert.CertPathBuilderException 错误,这些网站在常规浏览器中加载正常,但即使在将证书添加到 CF 密钥库后,cfhttp 仍然出现错误并重新启动。

当目标站点服务器证书配置存在信任链问题时会发生这种情况 - 当一个或多个信任链路径要求浏览器执行 "extra download" 证书时。这可能是因为单个信任链路径中缺少中间证书,或者因为信任链中有多个分支具有不同的指纹,并且来自一个或多个分支的一个或多个证书未被提供。

如果您 运行 通过像 ssllabs.com 这样的 SSL 分析器访问目标站点 - 例如 https://globalsign.ssllabs.com/analyze.html?d=www.cliftoncameras.co.uk&hideResults=on - 你会看到他们的中间证书 Starfield Secure Certificate Authority - G2 没有被他们的服务器提供服务,这迫使客户端执行 "extra download" - 这对大多数适当的人来说不是问题浏览器,但 cfhttp 使用的 Java 客户端需要服务器直接提供几乎所有中间证书和根证书。直到几年前,大多数移动操作系统都是一样的。

因此,理想的解决方案是联系 cliftoncameras 并让他们的服务器管理员安装正确的 Starfield 中级证书,以便正确提供服务。

您这边可能的解决方法是在您的 CF 密钥库中安装 Starfield Secure Certificate Authority - G2 中间证书。

如果你不能让密钥库工作,也许你会想试试这个。

创建专用命令行可执行文件 (.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.txt 是执行 clifton.exe 的结果)。


制作方法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
  • 打开一个终端 window 并使用 dart --version 测试 Dart 的安装(您应该可以 运行 从任何文件夹中安装 dart,如果需要,将 dart 添加到您的 PATH 中)
  • 在终端 window 中,使用 cd c:\bin
  • 将目录更改为 c:\bin
  • 接下来,运行dart2native clifton.dart -o clifton.exe
  • 如果编译顺利,你应该在 c:\bin 中包含三个文件:clifton.dartclifton.exe 和证书 sfig2.crt.pem.
  • 如果您愿意,可以在终端 window 中测试 运行 clifton.exe,这应该会创建 clifton.txt 文件。
  • 测试调用clifton.exe的ColdFusion页面,等待clifton.txt然后输出内容。

如果在生产环境中部署,则需要文件 clifton.exesfig2.crt.pem(证书)。

祝你好运!

在我的开发平台上添加了

-Dcom.sun.security.enableAIAcaIssuers=true

到ColdFusion2018\cfusion\bin\jvm.config

文件中的java.args

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

感谢@agreax 提供此解决方案

感谢@sevroberts,他的回答可能是正确的,尽管我无法让它工作。生产主机将 SSL 证书安装到密钥库中,并通过这种方式成功解析。他们说:

If you use FireFox browser and click on the lock icon when browsing the URL you are wanting to have the cfhttp request access you can then get the more info and click the View Certificate option. You will need to download the PEM (cert) not the Chain. Once downloaded, you need to run the keytool in order to import it to the keystore.

If you are using the default JRE within your JVM for ColdFusion you will need to install a JDK to your development machine. You can see the details and steps we have listed on our wiki regarding the commands from the command prompt to import the SSL into the store. https://wiki.hostek.com/ColdFusion_Tips_%26_Tricks#Fixing_cfhttp_Connection_Failures_with_Keytool

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