mysqli::ssl_set() 函数必须在调用 mysqli::real_connect() 之前调用,否则设置将不会生效。错误的调用顺序是最常见的疏忽之一。
错误示例:
$conn = new mysqli();
$conn->real_connect('db.m66.net', 'user', 'pass', 'database');
$conn->ssl_set('/path/client-key.pem', '/path/client-cert.pem', '/path/ca.pem', NULL, NULL);
正确示例:
$conn = new mysqli();
$conn->ssl_set('/path/client-key.pem', '/path/client-cert.pem', '/path/ca.pem', NULL, NULL);
$conn->real_connect('db.m66.net', 'user', 'pass', 'database');
使用 real_connect() 连接时,若未传入 MYSQLI_CLIENT_SSL 标志,连接可能不会启用 SSL,即使调用了 ssl_set()。
$conn->real_connect('db.m66.net', 'user', 'pass', 'database', null, null, MYSQLI_CLIENT_SSL);
查看 PHP 是否启用了 OpenSSL 扩展非常关键。可以通过 phpinfo() 或命令行执行 php -m | grep openssl 来确认。如果未启用,PHP 将无法建立 SSL 加密连接。
服务器端也必须开启 SSL,并且提供合法的证书和 CA 文件。可以通过以下 SQL 语句确认:
SHOW VARIABLES LIKE '%ssl%';
如果结果显示 have_ssl 为 DISABLED,则无论客户端如何设置,SSL 都无法生效。
一些旧版本的 PHP 或 libmysqlclient 连接库可能不支持 SSL,或需要特定编译选项支持。建议使用 mysqlnd 驱动,因为其原生支持 SSL 且更现代化。
即便一切配置正确,仍需验证连接是否启用了加密。可以通过以下语句查看实际加密状态:
$result = $conn->query("SHOW STATUS LIKE 'Ssl_cipher'");
$row = $result->fetch_assoc();
if (!empty($row['Value'])) {
echo "SSL 启用,加密算法为: " . $row['Value'];
} else {
echo "SSL 未启用";
}
如果返回为空,说明 SSL 实际上并未启用。
在某些环境中,如果使用的是 localhost,连接可能退回到 Unix socket,从而绕过网络层 SSL。建议显式使用主机名或 IP 地址,例如:
$conn->real_connect('db.m66.net', 'user', 'pass', 'database');