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

PHP在证书CN与主机名不匹配但主机名在SAN中时能否完成SSL握手?

PHP连接Tomcat SAN证书异常排查与修复方案

核心问题背景

原有正常运行的PHP程序在Tomcat更换SAN证书后出现连接失败,已确认访问域名在SAN列表内、手动指定cafile仍无法连接,PHP版本为7.3。

分步排查与修复方案

  • 第一步:先验证服务端证书配置有效性

    不要默认证书配置正确,直接通过OpenSSL命令拉取服务端实际返回的证书做校验:
    openssl s_client -connect 你的访问域名:8443 </dev/null 2>/dev/null | openssl x509 -noout -text | grep -A 10 "Subject Alternative Name"
    
    重点检查3个点:
    • 输出的SAN列表中,访问域名必须是DNS类型的条目,用IP访问时必须配置对应IP类型的SAN条目,类型不匹配时校验直接失败
    • 通配符SAN仅支持匹配一级子域名,例如*.example.com无法匹配a.b.example.com
    • 拉取到的证书链必须完整,包含叶子证书、中间CA证书、根证书,缺少中间证书时哪怕cafile指定正确也会握手失败
  • 第二步:修正SSL上下文与SoapClient参数

    你当前代码有两个高频踩坑点:一是本地加载WSDL时,SoapClient不会自动提取location里的域名作为SSL校验主机名,会默认用本地WSDL路径做匹配,必然失败;二是缺少SNI、手动指定peer_name的关键配置。
    修正后的代码示例:
    <?php
    $host = "server_name";
    $username = "******";
    $password = "******";
    
    $context = stream_context_create([
        'ssl' => [
            'verify_peer' => true, // 生产环境请勿关闭校验,避免中间人攻击
            'verify_peer_name' => true,
            'allow_self_signed' => true, // 仅自签证书保留该配置,正规CA签发证书请删除此行
            'cafile' => 'C:\path\to\your\fullchain.cer', // 必须传入包含完整证书链的文件,不能只传叶子证书
            'SNI_enabled' => true, // Tomcat多证书托管场景必须开启,否则会拿到默认证书而非目标域名证书
            'peer_name' => $host, // 手动强制指定SSL校验的主机名,解决本地WSDL导致的校验名错误
        ]
    ]);
    
    $client = new SoapClient("C:\inetpub\wwwroot\PhoneSetup\axl\AXLAPI.wsdl",
        [
            'trace'=>true,
            'exceptions'=>true,
            'location'=>"https://".$host.":8443/axl",
            'login'=>$username,
            'password'=>$password,
            'stream_context'=>$context,
            'cache_wsdl' => WSDL_CACHE_NONE, // 关闭WSDL缓存,避免旧缓存导致配置不生效
        ]
    );
    
    try {
        $response = $client->getPhone(["name"=>"SEP28AFFDA53393"]);
        var_dump($response);
    } catch (SoapFault $e) {
        // 打印OpenSSL底层错误,直接定位失败原因
        while ($opensslErr = openssl_error_string()) {
            var_dump("OpenSSL错误: ".$opensslErr);
        }
        var_dump("SOAP错误: ".$e->getMessage());
    }
    ?>
    
  • 第三步:排查环境兼容与权限问题

    运行如下代码检查PHP的OpenSSL环境配置:
    <?php
    var_dump(openssl_get_cert_locations());
    var_dump(OPENSSL_VERSION_TEXT);
    ?>
    
    重点确认:
    • PHP绑定的OpenSSL版本不低于1.0.2,低于该版本对SAN扩展的识别存在已知bug,无法正确匹配多SAN条目、国际化域名的SAN配置
    • 你配置的cafile路径格式正确,且IIS运行PHP的账号(通常是IUSR、IIS_IUSRS用户组)对该证书文件有读取权限,权限不足时cafile会静默加载失败,退回到系统默认CA路径校验
  • 第四步:分层验证排除问题

    先跳过SoapClient,直接用HTTP流测试SSL连接是否正常,排除SoapClient本身的参数干扰:
    <?php
    // 传入你配置好的ssl上下文
    $result = file_get_contents("https://".$host.":8443/axl", false, $context);
    while ($err = openssl_error_string()) {
        var_dump($err);
    }
    var_dump($result);
    ?>
    
    如果该请求可以正常返回结果,说明SSL配置本身没问题,故障点就在SoapClient的参数覆盖或WSDL缓存上。

常见错误对应原因

  • 报错certificate subject name does not match target host name:peer_name未正确指定,或SAN条目确实不匹配、类型错误
  • 报错unable to get local issuer certificate:证书链不完整、cafile路径错误/权限不足
  • 报错no suitable signature algorithm:证书使用的签名算法(如Ed25519)过新,当前PHP绑定的OpenSSL版本不支持

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 23:06:07