<p>MySQL SSL 连接通过 .env 中 DB_SSL_MODE 控制开关,需在 config/database.php 中手动注入 PDO::MYSQL_ATTRSSL* 选项;required 强制加密,preferred 有则用、无则降级,disabled 彻底禁用;证书路径须为绝对路径且仅在非 disabled 模式下生效。</p>

MySQL SSL 连接在 .env 里怎么开关?
直接改 DB_SSL_MODE 环境变量就行,Laravel 本身不认这个键,得自己塞进连接配置里。默认 MySQL 驱动(mysql)不启用 SSL,哪怕你配了证书路径也不会自动用——它只在明确要求时才握手加密。
-
DB_SSL_MODE=required:强制加密,连不上就报SSL connection error -
DB_SSL_MODE=preferred:有 SSL 就用,没就退化为明文(MySQL 8.0+ 支持) -
DB_SSL_MODE=disabled:彻底关掉,即使其他 SSL 参数都填了也忽略 - 别设成
verify_ca或verify_identity后不配证书路径,否则PDO::__construct()会直接抛SQLSTATE[HY000] [2002]类错误
Laravel 的 config/database.php 怎么注入 SSL 参数?
不能只靠 .env,得手动把环境变量映射到数据库配置数组里。Laravel 的 mysql 配置项默认没有 options 键,而 PDO 的 SSL 设置必须走 PDO::MYSQL_ATTR_SSL_* 常量。
- 在
config/database.php的mysql数组里加'options' => [],再根据env('DB_SSL_MODE')动态塞值 -
PDO::MYSQL_ATTR_SSL_CA、PDO::MYSQL_ATTR_SSL_CERT、PDO::MYSQL_ATTR_SSL_KEY这三个常量只在DB_SSL_MODE不是disabled时才需要传路径 - 路径必须是绝对路径,用
database_path('ssl/ca.pem')比相对路径靠谱,不然部署时容易报failed to load ca certificate - 如果用的是 MySQL 5.7,
preferred模式无效,它只认required和disabled,设错会导致本地能连、线上连不上
为什么 DB_SSL_MODE=required 在 Homestead/Valet 下总失败?
开发环境的 MySQL 通常没开 SSL 支持,或者服务端证书和客户端不匹配。不是 Laravel 配错了,而是 MySQL 本身没准备好。
- 先连进 MySQL 执行
SHOW VARIABLES LIKE '%ssl%';,确认have_ssl = YES且ssl_ca非空 - Homestead 默认关 SSL,得改
/etc/mysql/my.cnf加ssl-ca/ssl-cert/ssl-key并重启mysql服务 - Valet 用户注意:
brew services restart mysql不会重载 SSL 配置,得手动 kill 进程再brew services start mysql - 测试是否真走 SSL:连上后执行
STATUS;,看输出里有没有SSL: Cipher in use is这一行
生产环境开启 SSL 后查询变慢,是不是该关掉?
不是性能问题,是握手阶段多了一次 RTT + 密钥协商,但单次影响在毫秒级。真正拖慢的往往是证书验证逻辑或网络中间件(比如某些云数据库代理会缓存 SSL 握手结果,但首次仍慢)。
- 用
DB_SSL_MODE=preferred能避免首次连接卡顿,又保留加密能力 - 别在
config/database.php里硬编码证书路径,不同服务器环境证书位置可能不同,统一用env('DB_SSL_CA_PATH')动态读取 - 如果用了 RDS/Aurora,AWS 提供的根证书是公开的,但必须用
verify_ca模式才校验;设成required反而跳过校验,起不到防中间人作用 - 最常被忽略的一点:Laravel 的
DB_CONNECTION切换不会自动重连,连接池里已建的明文连接不会升级为 SSL,要等连接超时或手动DB::reconnect()


















