<p>Hyperf 连 MySQL 开启 SSL 加密需三者同时满足:服务端证书加载成功、用户权限强制 REQUIRE SSL、客户端驱动完成 TLS 握手。必须验证 ssl_ca/cert/key 路径存在且可读、Ssl_version 非空、require_secure_transport 合理启用,并在 Hyperf 配置中显式传入 PDO::MYSQL_ATTRSSL* 三项绝对路径,用户须执行 ALTER USER ... REQUIRE SSL,测试务必使用 127.0.0.1 而非 localhost。</p>

Hyperf 项目里连 MySQL 开启 SSL 加密,不是加个配置就自动生效——必须服务端证书加载成功、用户权限强制 REQUIRE SSL、客户端驱动真实完成 TLS 握手三者全满足,缺一不可。
确认 MySQL 服务端 SSL 真正就绪
很多 Hyperf 启动报错或连接明文,根源在服务端没真正启用 SSL。只看 have_ssl = YES 不够,得验证运行时状态:
-
SHOW VARIABLES LIKE 'ssl_ca'、ssl_cert、ssl_key必须返回非空的绝对路径,且文件真实存在 -
SHOW STATUS LIKE 'Ssl_version'必须有输出(如TLSv1.2),若为空说明 mysqld 启动时跳过了 SSL 初始化 - 检查 MySQL 错误日志(如
/var/log/mysql/error.log),搜SSL或Failed to set up SSL,常见原因是server-key.pem权限不是600或路径被 mysql 用户读不到 - 别忽略
require_secure_transport = ON—— 它能强制拒绝所有非 SSL 连接,但会干掉localhost的 Unix socket,Hyperf 本地开发若用127.0.0.1就没事,用localhost就连不上
Hyperf 配置 MySQL SSL 连接参数
Hyperf 默认用 hyperf/database + pdo_mysql,它不自动继承系统级 SSL 设置,必须显式传入 SSL 选项。在 config/autoload/databases.php 中改 mysql 配置:
- 把
'options' => []扩展为包含 PDO::MYSQL_ATTR_SSL_CA、PDO::MYSQL_ATTR_SSL_CERT、PDO::MYSQL_ATTR_SSL_KEY 三项,值为对应 PEM 文件的绝对路径 - 例如:
'options' => [ PDO::MYSQL_ATTR_SSL_CA => '/var/lib/mysql/ca.pem', PDO::MYSQL_ATTR_SSL_CERT => '/var/lib/mysql/client-cert.pem', PDO::MYSQL_ATTR_SSL_KEY => '/var/lib/mysql/client-key.pem', ], - 注意:Hyperf 8.x 默认用
mysql协议,不支持ssl-mode=VERIFY_IDENTITY这类高阶参数;若需主机名校验,得换用mysqli驱动并手动封装连接逻辑 - 如果只设
PDO::MYSQL_ATTR_SSL_CA,而服务端是REQUIRE SSL,连接会直接失败,报Access denied for user,不是证书错误
MySQL 用户必须显式声明 REQUIRE SSL
Hyperf 连的账号权限决定了是否允许非加密连接。即使服务端开了 SSL,只要用户没绑 REQUIRE SSL,PDO 仍可降级走明文:
- 新建用户命令:
CREATE USER 'hyperf_app'@'%' IDENTIFIED BY 'pwd' REQUIRE SSL; - 已有用户(MySQL ≥ 8.0.22):
ALTER USER 'hyperf_app'@'%' REQUIRE SSL; - 验证是否生效:
SELECT user, host, ssl_type FROM mysql.user WHERE user = 'hyperf_app';,ssl_type应为ANY - 切记:用
127.0.0.1测试,不要用localhost—— 后者走 socket,完全绕过 SSL 校验
验证连接是否真加密
Hyperf 启动后不能只信配置,得进容器或服务器上连上去查实时连接状态:
- 用
mysql -h your_db_host -u hyperf_app -p --ssl-mode=REQUIRED手动连,成功后执行:SHOW STATUS LIKE 'Ssl_cipher';,返回非空值才表示当前连接已加密 - 在 Hyperf 应用里执行任意 SQL 后,查 MySQL 的
information_schema.PROCESSLIST,看该连接的SSL_TYPE是否为CYIPHER - 如果
Ssl_cipher是空,但have_ssl = YES,大概率是 PDO 配置漏了某一项,或证书路径写错/权限不对 - Hyperf 日志里不会打印 SSL 握手细节,调试只能靠 MySQL 侧状态和错误日志
最易被忽略的是:Hyperf 的 pdo_mysql 驱动对 SSL 参数极其敏感,少一个路径、路径权限不对、私钥带密码,都会静默失败或降级;而 MySQL 服务端的 require_secure_transport = ON 虽安全,但会让所有未适配 SSL 的脚本、健康检查、备份工具瞬间中断——上线前必须逐个验证。



















