我想使用来自PHP应用程序(脚本)的SSL身份验证连接到WebSphere MQ队列。
队列管理器版本为7.0或7.5
MQ客户端版本是8.0
PHP版本是7.0(docker)
使用PHP mqseries pecl扩展v0.15(带有自定义修复程序)
到目前为止,我能够在没有SSL连接的情况下进行连接。
到目前为止,这是我必须执行的步骤:
我已经安装了适用于Linux的WebSphere MQ Client v8(以我的情况为CentOS)
我已经下载了mqseries php扩展的PECL 0.15版本。 (扩展中有一个小错误,我不得不重新编译它才能使其正常工作。我以前在MQGET上遇到了分段错误)。
我将mqseries.so链接到php并启用了扩展名。
我成功(没有SSL)
连接到队列管理器
打开队列进行阅读
获取队列中的消息
关闭连接
当我在脚本中将USE_SSL
设置为true时,我收到错误代码2393,表示“ An MQCONN or MQCONNX call was issued with SSL configuration options specified, but an error occurred during the initialization of the SSL environment.
”。此错误消息非常通用,无法帮助我指出问题出在哪里。MQ_KEYSTORE
设置为/path/to/my/key
,我的文件名是key.kdb
,并且具有与该documentation建议的级别相同的key.sth
脚本中的MQ_SSL_CIPHER_SPEC
与在队列管理器上为指定的MQ_CHANNEL_SSL
指定的相同。多次检查。这些不是与JMS连接一起使用的Cipher Suite
安全高速缓存已在队列管理器上刷新。
在服务器端,我检查了队列管理器的错误日志,但似乎没有看到我的频道名称。我之所以说“似乎”,是因为有很多杂音,并且其中很多???
频道名称。所以我觉得它由于某种原因没有到达队列管理器。
我还使用了在MQ Client安装bin文件夹中找到的“ amqssslc
”命令来测试我的ssl配置。与使用PHP脚本相比,我得到了相同的错误。
我还使用WireShark在相应的MQ_PORT
上嗅探数据包。软件包的内容包含证书信息。因此,有些事情看起来像是SSL握手。
我现在对如何调试外壳一无所知。有谁知道下一步要检查什么?我应该检查MQ Client安装上的连接日志吗?
这是connection using SSL in PHP的示例
这是我的MQ脚本的简化版本(我删除了输出)。为了安全起见,未公开某些常量。
所有MQSERIES_ *常量都在扩展名中定义
所有MQ_ *都是用于测试我的脚本的硬编码参数,但是它们的定义未出现在脚本摘录中。
<?php
// Constants defined here
$options = [
'Version' => MQSERIES_MQCNO_VERSION_4,
'Options' => MQSERIES_MQCNO_STANDARD_BINDING,
'MQCD' => [
'Version' => 7,
'ChannelName' => MQ_CHANNEL,
'ConnectionName' => sprintf('%s(%s)', MQ_HOST, MQ_PORT),
'TransportType' => MQSERIES_MQXPT_TCP,
]
];
if (USE_SSL) {
$options['MQSCO'] = [
'KeyRepository' => MQ_KEYSTORE
];
$options['MQCD']['ChannelName'] = MQ_CHANNEL_SSL;
$options['MQCD']['SSLCipherSpec'] = MQ_SSL_CIPHER_SPEC;
}
mqseries_connx(MQ_QUEUE_MANAGER, $options, $conn, $comp_code, $reason );
$mqods2 = [
'ObjectType' => MQSERIES_MQOT_Q,
'ObjectName' => MQ_QUEUE
];
mqseries_open($conn, $mqods2, MQSERIES_MQOO_INPUT_AS_Q_DEF | MQSERIES_MQOO_FAIL_IF_QUIESCING, $obj, $comp_code, $reason);
$gmd = [];
$gmo = [
'Options' => MQSERIES_MQGMO_FAIL_IF_QUIESCING | MQSERIES_MQGMO_WAIT, 'WaitInterval' => 3000
];
$msg = "";
$data_length = "";
for ($i = 0; $i < 1000; $i++) {
mqseries_get($conn, $obj, $gmd, $gmo, 10000, $msg, $data_length, $comp_code, $reason);
if ($reason === 2033) {
printf("No more messages to process\n");
break;
}
// Business logic
}
mqseries_disc($conn, $comp_code, $reason);
?>
更新
使用我不知道存在的客户端日志。最终,我们发现我们的服务器未使用正确的证书。服务器的证书实际上是自签名的,因此未授予我们访问权限,因为我们的.kdb文件没有公钥。我们将服务器自己的公钥添加到.kdb文件中,从而使该步骤得以实现。
如JoshMC的评论中所建议,对于我们的下一个问题,我们怀疑密钥库文件中的标签错误。我们没有从.kdb文件中指定特定标签。从docs“
For queue managers and clients respectively, the following sources are searched in sequence for a non-empty value. The first non-empty value determines the certificate label. The certificate label must exist in the key repository. If no matching certificate in the correct case and format is found that matches a label, an error occurs and the SSL or TLS handshake fails.
”并且它还指出“
The certificate label cannot contain spaces.
”。明天,我将使用正确的标签命名并发送特定的标签名称再试一次。我将尝试查看名称约定
ibmwebspheremq<user_that_runs_the_php_process>
是否实际上影响了有效性。更新2
终于解决了。如JoshMC所述,私钥需要具有特定标签ibmwebspheremq。我还没有尝试使用CertificateLabel。下周我可能会深入探讨。
最初,我们使用ibm中的GUI(ikeyman)来生成.kdb文件。但是我们发现它有很多错误。例如,它使用相同的标签(从证书自动生成的标签)导入两次私钥。无法编辑标签名称(因此存在连接问题)。为了解决这一部分,我们使用了命令行工具
ikeycmd
,该工具基本上在命令行上提供了相同的功能(减去错误)。要运行该命令,您需要IBM jre(未验证,需要检出)并以java com.ibm.gsk.ikeyman.ikeycmd
身份运行它。从这里开始,IBM网站上提供了有关如何创建证书,重命名标签,检查详细信息等的大量文档。无数的乐趣!
最佳答案
完整安装IBM MQ客户端后,客户端错误将记录到以下目录:/var/mqm/errors
错误(如果有的话)将记录到文件AMQERR01.LOG
中(它将与另外两个以02
和03
结尾的文件一起轮换。如果错误是MQ所不希望的,它也可能会创建一个以结尾的文件.FDC
以及其他详细信息。
如果在客户端发送通道名称之前进行通道协商期间连接失败,则队列管理器将记录通道名称???
。如果IBM MQ队列管理器正在使用v7.5或更低版本,则直到TLS握手完成后才交换通道名称。
在v8和更高版本的客户端连接到v8和更高版本的队列管理器的情况下,MQ将在TLS协商期间使用TLS SNI交换通道名称,但是我不确定MQ是否也得到了增强,可以记录此通道名称,在以前的版本中它记录的
检查您的客户端???
是否具有私钥。 MQ使用三种方式来标识要使用的私钥。
在MQ Client v7.5和更早版本中,私钥的标签必须为:ibmwebspheremq<user_that_runs_the_php_process>
使用MQ客户端v7.5和更早版本,替代方法是将私钥设置为默认证书,并确保在执行程序的环境中设置了以下环境变量。请注意,这也适用于8.0.0.7/9.0.0.1,但与之相比,我更喜欢下一种方法。 AMQ_SSL_ALLOW_DEFAULT_CERT=1
在MQ Client v8和更高版本中,可以在key.kdb
的CertificateLabel=anylabelvalue
节中使用SSL
。下面的例子:SSL:
CertificateLabel=anylabelvalue
mqclient.ini
设置记录在IBM MQ v8 KC页面“ SSL
stanza of the client configuration file”中。
可以从CertificateLabel
复制mqclient.ini
的模板,并将其放在应用程序执行所在的目录中。也可以通过环境变量指定该位置,如果未设置该变量并且在应用程序执行的同一目录中找不到该变量,则MQ会在文件的其他几个位置中查找。 MQ查找该文件的各种方式记录在IBM MQ v8 KC页面“ Location of the client configuration file”中
关于php - 如何在PHP中使用SSL认证连接到WebSphere MQ队列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46084567/