【问题标题】:CFHTTP unable to find valid certification path to requested targetCFHTTP 无法找到请求目标的有效证书路径
【发布时间】:2020-09-14 10:03:22
【问题描述】:

我正在寻找从网站上抓取数据,其他 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 克利夫顿相机 - 文件 c:\ColdFusion2018\jre\lib\security\cliftoncameras.cer

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

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

我还能做什么?

【问题讨论】:

  • 更新 JRE 时是否将证书导入到正确的密钥库文件中?如您的示例所示,它将不再是 ColdFusion 附带的默认位置。
  • 我都试过了,一次一个,具体取决于使用的是哪一个。谢谢
  • 假设您可以访问 jvm.config 设置,请备份该文件。然后修改它以启用调试。 IE。添加-Djavax.net.debug=all 并重启CF。 docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/…
  • this was working last week 上周和本周之间发生了什么变化……更新、代码更改……?

标签: coldfusion ssl-certificate cfhttp


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 谢谢,我对 cliftoncameras 的作用没有任何发言权,所以我会尝试添加中间证书。
  • 我安装了许多 Starfield 证书,包括来自 SSL 分析器的证书 - 没有任何区别。
  • Daniel Cook - 有趣的是,cfhttp 调用适用于 trycf.com,但仅适用于 Lucee 5。无法弄清楚原因。我尝试安装“Starfield Secure...”证书和 cliftoncameras 证书,但仍然没有任何乐趣。毫无疑问,我错过了一些东西,但不确定是什么......无论如何,this thread mentioned a JVM arg 对我有用:-Dcom.sun.security.enableAIAcaIssuers=true。步骤 1) 备份 jvm.config 文件(别忘了这样做) 2) 添加 -Dcom.sun.security.enableAIAcaIssuers=true 参数 3) 重启 CF 服务器
  • Agreax 做到了!非常感谢,我只需要看看我是否可以说服主机在实时服务器上进行更改!
  • @Agreax 如果您想写一个小答案,我会给予信任。
【解决方案2】:

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

创建一个专用的命令行可执行文件 (.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
  • 打开一个终端窗口并使用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的ColdFusion页面,等待clifton.txt输出内容。

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

祝你好运!

【讨论】:

  • 谢谢,感谢您的详细建议。我认为是时候在进行如此大量的工作之前就该问题与零售商联系。
  • 不客气。经过测试,即使你需要安装 Dart 也可以在不到半小时的时间内完成。
  • 好吧,那我差不多卖光了!我需要提取几个 URL,所以需要一个 urls / 导出文件数组,以及一个循环来创建它们。我会考虑修改您提供的代码。
  • 没错。如果您遇到困难,请告诉我。您可以多次拨打saveSourceToFile(_client, _uri, _sink);。你可以保持相同的_client 只是传递不同的_uri_sink。由于每个调用的异步性质,您可能需要使用递归。
  • 虽然有效!谢谢。我意识到 cfexecute 没有运行,快速的互联网搜索提醒了我原因。共享生产主机提供商也不想启用它。 wiki.hostek.com/ColdFusion_FAQs#Can_I_use_CFExecute.3F
【解决方案3】:

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

-Dcom.sun.security.enableAIAcaIssuers=true

到ColdFusion2018\cfusion\bin\jvm.config文件中的java.args

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

感谢@agreax 提供此解决方案

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

如果您使用 FireFox 浏览器并在浏览您希望获得 cfhttp 请求访问的 URL 时单击锁定图标,则您可以获得更多信息并单击查看证书选项。 您将需要下载 PEM(证书)而不是链。下载后,您需要运行 keytool 才能将其导入密钥库。

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

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

【讨论】:

  • 所以主机能够通过安装证书来解决它?
  • 这就是他们所说的,但是我遇到了另一个供应商的另一个 CFHTTP 问题 - 在我将他们的 SSL 证书安装到 DEV 上的密钥库之后,一切正常!这甚至不是生产的问题。不一致的问题真是令人头疼
  • 编辑 - 呃....不一致的结果真是太痛苦了。您是否使用与 Prod 相同的配置? CF 或 JVM 的差异可能可以解释这一点。
猜你喜欢
  • 2020-11-11
  • 2011-10-18
  • 1970-01-01
  • 1970-01-01
  • 2023-01-03
相关资源
最近更新 更多