You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用带客户端证书的SoapClient连接SOAP WebService失败排查

问题:PHP SoapClient调用带客户端证书的本地SOAP服务失败(Could not connect to host)

搭建了本地SOAP服务器,使用客户端证书进行连接验证。通过SoapUI调用服务时可正常连接,但使用PHP的SoapClient却无法成功。尝试用file_get_contents带着相同的流上下文能正常获取WSDL,但将该上下文传入SoapClient构造函数时,会抛出SoapFault: Could not connect to host异常。

代码示例

<?php

$context = stream_context_create(
    [
        'ssl' => [
            'local_cert' => __DIR__ . '/client.crt',
            'local_pk' => __DIR__ . '/client.key',
            'verify_peer' => false,
            'verify_peer_name' => false,
            'allow_self_signed' => false,
        ]
    ]
);

$url = 'https://localhost:4430?WSDL';

echo "From file_get_contents: ".(file_get_contents($url, false, $context)).PHP_EOL;

echo "== Making the call ==".PHP_EOL;

try {
    $client = new SoapClient($url,
        [
            'stream_context' => $context,
        ]);

    echo "From ws call: ".$argv[1] . ' + ' . $argv[2] . ' = ' . $client->Add([
            'intA' => $argv[1],
            'intB' => $argv[2],
        ])->AddResult;
} catch (SoapFault $soapFault) {
    echo $soapFault->getMessage();
}

echo PHP_EOL;

运行输出

From file_get_contents: <?xml version="1.0" encoding="UTF-8"?>
<definitions name="Calculator"
             xmlns = "http://schemas.xmlsoap.org/wsdl/"
             targetNamespace="urn:Calculator"
             xmlns:tns="urn:Calculator"
             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
             xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
    <message name="addRequest">
        <part name="a" type="xsd:int"/>
        <part name="b" type="xsd:int"/>
    </message>
    <message name="addResponse">
        <part name="result" type="xsd:int"/>
    </message>
    <portType name="AddPort">
        <operation name="add">
            <input message="tns:addRequest"/>
            <output message="tns:addResponse"/>
        </operation>
    </portType>
    <binding name="AddBinding" type="tns:AddPort">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="add">
            <soap:operation soapAction="urn:CalculatorAction"/>
            <input>
                <soap:body use="encoded" namespace="urn:Calculator" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
            </input>
            <output>
                <soap:body use="encoded" namespace="urn:Calculator" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
            </output>
        </operation>
    </binding>
    <service name="WSDLService">
        <documentation>Returns a greeting string.</documentation>
        <port name="AddPort" binding="tns:AddBinding">
            <soap:address location="https://localhost:4430/calculator_server.php?wsdl"/>
        </port>
    </service>
</definitions>
== Making the call ==
Could not connect to host

问题分析与解决方案

1. 修正SSL上下文的自签名证书配置

本地测试服务器大概率使用自签名证书,但当前上下文里allow_self_signed设为false,会导致SoapClient验证服务器证书失败。修改该配置为true:

$context = stream_context_create(
    [
        'ssl' => [
            'local_cert' => __DIR__ . '/client.crt',
            'local_pk' => __DIR__ . '/client.key',
            'verify_peer' => false,
            'verify_peer_name' => false,
            'allow_self_signed' => true, // 改为true
        ]
    ]
);

2. 确保客户端证书与密钥的兼容性

部分PHP环境对分开的.crt和.key文件支持不佳,建议将两者合并为一个PEM格式文件:

# 合并证书和密钥到一个文件
cat client.crt client.key > client.pem

然后修改上下文配置,只保留local_cert指向合并后的文件:

'ssl' => [
    'local_cert' => __DIR__ . '/client.pem',
    'verify_peer' => false,
    'verify_peer_name' => false,
    'allow_self_signed' => true,
]

如果你的密钥设置了密码,还需要在SSL上下文里添加'passphrase' => '你的密钥密码'。

3. 调试SoapClient请求细节

添加trace选项可以获取请求的详细信息,帮助定位具体错误:

try {
    $client = new SoapClient($url,
        [
            'stream_context' => $context,
            'trace' => true, // 开启请求追踪
            'exceptions' => true,
        ]);

    // ... 调用代码
} catch (SoapFault $soapFault) {
    echo $soapFault->getMessage() . PHP_EOL;
    // 打印最后一次请求的头部和内容
    echo "Request Headers:\n" . $client->__getLastRequestHeaders() . "\n";
    echo "Request Content:\n" . $client->__getLastRequest() . "\n";
    // 同时查看PHP错误日志,里面会有更详细的SSL连接失败原因
}

4. 验证WSDL中的服务地址

WSDL里的<soap:address location="https://localhost:4430/calculator_server.php?wsdl"/>是SoapClient实际调用的地址,需要确认该路径同样接受客户端证书验证,且可以正常访问。


内容的提问来源于stack exchange,提问作者Muc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 19:46:18