15

尝试访问 URL 时,如何在 PHP 流上下文中强制使用 TLSv1.0 https

我正在寻找类似的东西:

$context = stream_context_create(
  array(
    'ssl' => array(
      'protocol_version' => 'tls1',
    ),
  ));
file_get_contents('https://example.com/test', false, $context);

背景

实际上,在使用PHPSoapClient. 不幸的是,我尝试连接的服务器仅支持 SSLv3.0/TLSv1.0,并且在默认的 TLSv1.1 协商中失败。因此,我想明确地将ssl://传输协议设置为 TLSv1.0。

4

4 回答 4

19

PHP 5.6+ 用户

这是PHP 5.6 OpenSSL Changes 页面上记录的一个新特性。

在撰写本文时,PHP5.6 处于 Beta1 中,因此它并不过分有用。未来的人——你很幸运!

未来就在我们身上。PHP 5.6 是一个东西,应该鼓励使用它。请注意,它弃用了一些相当广泛使用的东西,如 mysql_* 函数,因此在升级时应小心。

其他所有人

@toubsen 在他的回答中是正确的 - 这不是直接可能的。详细说明他建议的解决方法......当解决供应商的 API 服务器未正确协商 TLSv1.2 到其支持的 TLSv1.0 的问题时,发送一小部分密码似乎允许协商正确完成。流上下文代码是:

$context = stream_context_create(
    [
        'ssl' => [
            'ciphers' => 'DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-SHA:KRB5-DES-CBC3-MD5:KRB5-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DES-CBC3-SHA:DES-CBC3-MD5:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:AES128-SHA:RC2-CBC-MD5:KRB5-RC4-MD5:KRB5-RC4-SHA:RC4-SHA:RC4-MD5:RC4-MD5:KRB5-DES-CBC-MD5:KRB5-DES-CBC-SHA:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DES-CBC-SHA:DES-CBC-MD5:EXP-KRB5-RC2-CBC-MD5:EXP-KRB5-DES-CBC-MD5:EXP-KRB5-RC2-CBC-SHA:EXP-KRB5-DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC2-CBC-MD5:EXP-KRB5-RC4-MD5:EXP-KRB5-RC4-SHA:EXP-RC4-MD5:EXP-RC4-MD5',
        ],
    ]
);

SOAP 用户

PHP 的 SOAP 客户端不使用 curl,它似乎也不使用使用stream_context_set_default. 因此,创建的上下文需要在第二个参数中传递给 SOAPClient 构造函数,如下所示:

$soap_client = new SOAPClient('http://webservices.site.com/wsdlfile.wsdl', array('stream_context' => $context));

为什么是那些密码?

在服务器上运行该命令openssl ciphers会为您提供上述格式的受支持密码列表。运行openssl ciphers -v会告诉您那些特定于 TLSv1.2 的内容。上面的列表是根据 OpenSSL 报告的所有非 TLSv1.2 密码编译而成的。

openssl ciphers -v | grep -v 'TLSv1.2' | cut -d ' ' -f 1 | tr "\n" ':'

于 2014-04-17T10:21:04.890 回答
6

如果有人想知道在发出 SOAP 请求时如何“禁用”TLSv1.0...

$parameters = array(
    'trace' => true,
    'exceptions' => true,
    'cache_wsdl' => WSDL_CACHE_NONE,
    'stream_context' => stream_context_create(array(
        'ssl' => array(
            'ciphers' => 'DEFAULT:!TLSv1.0:!SSLv3'
        ),
    )),
    'connection_timeout' => 15
);

$client = new SoapClient(YOUR_WSDL_URL_HERE, $parameters);

这里的关键部分是流上下文密码行。这表示使用默认密码,但不包括 TLSv1.0 密码(1.0 包也有 TLSv1.1 密码)。: 是密码包分隔符(包之间的内容)和 ! 这里是告诉它排除这个包(这是一个硬排除,所以如果它稍后出现在列表中,它仍然会被排除)。软排除是 - 字符,添加到列表末尾的是 + 字符。要按顺序添加,只需添加它,前面没有任何东西。

此处的密码信息:https ://www.openssl.org/docs/manmaster/man1/ciphers.html#CIPHER-LIST-FORMAT

编辑:无论出于何种原因,包括

'ssl_method' => SOAP_SSL_METHOD_TLS,

选项中的一部分确实让我头疼,并且在某些情况下无法连接。经过大量的故障排除和使用选项后,我终于意识到删除此设置并让它自动设置似乎已经解决了这个问题。

于 2017-10-16T18:48:55.443 回答
2

基地信息

该字段protocol_version仅对 HTTP 上下文(HTTP 1.0 与 1.1)有效,但不影响 SSL 上下文。

以下手册页列出了 PHP 的所有流上下文选项: 上下文选项和参数

对于所有基于 SSL 的流包装器,只有以下选项可用: SSL 上下文选项

可能的解决方案/解决方法

第一个建议:让服务器管理员修复他的服务器,而不是在你的客户端解决这个问题;-)

也许您可以使用SSL 流ciphers选项,在列表中只传递一个您的目标服务器支持的精确TLSv1.0 密码套件(这是 TLSv1.0 独有的)。

切换实施以使用 cURL 在这里很可能也无济于事,因为根据他们的邮件列表中的条目,没有强制某个 TLS 版本的选项 - 客户端将在需要时自动降级。

tl;博士

我目前知道没有办法显式强制 TLSv1.0 用于来自 PHP 的 SSL 连接。

于 2013-11-19T13:29:55.293 回答
0

我可以确认上述接受的答案不适用于 Ubuntu 12.04 和 PHP 5.4.33 组合。还发现我在尝试使用 openssl 和 curl 访问 https 端点时必须手动指定证书。在为企业应用程序开发集成时,我最终使用 RHEL 7 和 PHP 5.5 来实现可靠的解决方案。没有反对 Ubuntu,但在我的具体情况下它不起作用。

于 2014-11-03T03:43:23.557 回答