PHP连接启用TLS/SSL的MySQL需配置客户端证书、CA文件等,先确认服务端SHOW VARIABLES LIKE 'have_ssl'为YES,mysqli用ssl_set()(绝对路径)、PDO在DSN中指定sslca等参数(PHP 7.2+),并验证Ssl_cipher状态。

PHP 连接加密的 MySQL(即启用了 TLS/SSL 的 MySQL 服务器)不需要“解密”——你不是在解密数据库,而是在建立带证书验证的安全连接。关键在于配置 PHP 的 mysqli 或 PDO 扩展正确加载客户端证书、密钥和 CA 证书。
确认 MySQL 服务端已启用 SSL
不先确认服务端状态,客户端配再全也连不上。登录 MySQL 执行:
SHOW VARIABLES LIKE 'have_ssl';
返回 YES 才表示服务端支持 SSL;再查:
SHOW VARIABLES LIKE 'ssl%';
重点关注 ssl_ca、ssl_cert、ssl_key 对应的路径是否非空且可读。
立即学习“PHP免费学习笔记(深入)”;
- 如果
have_ssl是DISABLED,说明 MySQL 启动时没加--ssl-mode=REQUIRED或相关参数,客户端强制 SSL 会失败 - 服务端证书必须由可信 CA 签发,或使用自签名但客户端需显式信任其 CA 文件
- MySQL 8.0+ 默认要求 SSL 连接(尤其云托管如 AWS RDS、阿里云 RDS),跳过 SSL 会报错
SSL connection is required
PHP 使用 mysqli 启用 SSL 连接
mysqli 不通过 DSN 配置 SSL,而是调用 mysqli::ssl_set() 方法设置证书路径,且必须在 mysqli::real_connect() 之前调用。
-
mysqli::ssl_set()四个参数顺序固定:$key_file、$cert_file、$ca_file、$capath、$cipher;前三个为必需,后两个可传null - 所有路径必须是 PHP 进程有读取权限的绝对路径(不能用相对路径或 URL)
- 若只验证服务端身份(最常见场景),只需提供
$ca_file;若还需双向认证(服务端验证客户端),才需$key_file和$cert_file - 连接后建议检查:
var_dump($mysqli->get_client_info());和var_dump($mysqli->query("SHOW STATUS LIKE 'Ssl_cipher'")->fetch_row());确认实际启用了加密
PDO 连接时指定 SSL 参数
PDO 在 DSN 中通过 sslmode、sslcert、sslkey、sslca 等属性传参,但注意:这些参数名**不是标准 PDO 属性**,而是 MySQL 驱动(pdo_mysql)特有的,且仅在 PHP 7.2+ 完整支持。
- DSN 示例:
mysql:host=localhost;port=3306;dbname=test;charset=utf8mb4;sslmode=REQUIRED;sslca=/path/to/ca.pem;sslcert=/path/to/client-cert.pem;sslkey=/path/to/client-key.pem - PHP 7.1 及更早版本不识别
sslca等参数,会静默忽略,导致连接看似成功实则未加密 - 务必在
new PDO(...)后捕获异常,并检查$pdo->getAttribute(PDO::ATTR_SSL_MODE)返回值(如PDO::SSL_MODE_REQUIRED) - 若使用连接池或长连接(如 Swoole),证书文件必须在进程启动前就加载好,运行时修改环境变量或重载配置无效
常见错误与绕过陷阱
报错 SSL connection error: protocol version mismatch 或 Unable to set certificate verify locations 很可能不是代码问题,而是环境配置偏差。
- PHP 编译时未链接 OpenSSL(
php -m | grep openssl应输出openssl),或 OpenSSL 版本太低(如 PHP 用 OpenSSL 1.0.x,MySQL 服务端要求 1.2+) - 证书文件格式错误:MySQL 要求 PEM 格式,不能是 PFX/P12;私钥不能有密码(否则 PHP 无法自动解密)
- CA 文件内容不完整:例如只复制了
-----BEGIN CERTIFICATE-----段落,漏掉末尾的-----END CERTIFICATE----- - 误以为
mysqli_connect()的第 5–7 个参数是 SSL 设置——它们是旧版 MySQL 协议的超时/重连参数,与 SSL 无关
真正难的不是写几行代码,而是让 PHP、OpenSSL、MySQL 三者在证书链、协议版本、文件权限上对齐。调试时优先用 mysql --ssl-ca=... --ssl-cert=... --ssl-key=... 命令行验证证书可用性,再迁移到 PHP。











