thinkphp连接azure sql失败主因是ssl证书验证失败:azure使用私有ca签发证书,linux系统默认不含该根证书,且tp5/6均不自动加载系统ca库,必须显式提供绝对路径的microsoft根证书并正确配置dsn中encrypt=yes和trustservercertificate=no。

ThinkPHP 连接 Azure SQL Database 必须启用 SSL,且不能跳过证书验证——Azure 强制要求 TLS 1.2+ 加密,且默认不信任系统 CA 库,必须显式提供根证书路径。
为什么 Azure SQL Database 在 ThinkPHP 中连接失败?
常见错误是 PDO::__construct(): SSL connection failed 或 cURL error 60,本质不是密码错、端口不通,而是:Azure SQL 使用的证书由 Microsoft 的私有 CA(如 Baltimore CyberTrust Root)签发,Linux 系统自带 CA 包通常不含该根证书;PHP 的 OpenSSL 默认不自动补全中间链;ThinkPHP 5/6 均不会自动加载系统证书库,必须手动指定。
- Azure SQL 不接受
TrustServerCertificate=true(SQL Server 风格参数),该参数在 PDO_SQLSRV 中无效,写了也忽略 - 用
sqlsrv_connect()直连可设"TrustServerCertificate"=>false,但 ThinkPHP 的sqlsrv驱动封装层不透传该选项,必须走 DSN 或底层参数注入 - Windows 环境下 PHP 可能默认信任微软根证书,但 Linux 容器或 Docker 部署几乎必然失败
ThinkPHP 6 配置 Azure SQL 的 SSL 连接(推荐方案)
使用 sqlsrv 驱动 + 显式 DSN + 根证书路径。关键点:证书路径必须为绝对路径,且需在 DSN 中通过 Encrypt=yes;TrustServerCertificate=no; 明确声明,再配合 PDO::ATTR_EMULATE_PREPARES => false 避免预处理干扰加密握手。
- 下载 Azure 公共根证书:从 Microsoft Root Certificate Authority.crt 获取,保存为
/var/www/cert/microsoft-root.crt - 确认 PHP 进程可读:
ls -l /var/www/cert/microsoft-root.crt,权限建议644,属主为www-data或对应运行用户 - 在
config/database.php中配置 MSSQL 连接:
'sqlsrv' => [
'type' => 'sqlsrv',
'hostname' => 'your-server.database.windows.net',
'hostport' => 1433,
'database' => 'your-db',
'username' => 'your-user@your-server',
'password' => 'your-pass',
'charset' => 'utf8',
'prefix' => '',
'params' => [
\PDO::ATTR_EMULATE_PREPARES => false,
// 注意:以下两项必须写在 params 里,且键名是 PDO 常量
\PDO::ATTR_SSL_MODE => \PDO::SSL_MODE_REQUIRED,
\PDO::MYSQL_ATTR_SSL_CA => '/var/www/cert/microsoft-root.crt', // 此处为占位写法,实际 sqlsrv 不认 MYSQL_* 常量
],
'dsn' => 'sqlsrv:server=your-server.database.windows.net;Database=your-db;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30;',
],
⚠️ 注意:\PDO::MYSQL_ATTR_SSL_CA 对 sqlsrv 驱动完全无效——这是常见误配。真正起作用的是 DSN 中的 Encrypt=yes 和证书文件本身是否被 OpenSSL 加载。Linux 下需确保 OpenSSL 能识别该证书,可通过 openssl verify -CAfile /var/www/cert/microsoft-root.crt /dev/null 测试。
ThinkPHP 5 怎么办?
TP5 的 sqlsrv 支持更弱,params 白名单未放开 SSL 相关常量,DSN 是唯一可控入口。你只能靠 DSN 字符串硬编码所有参数,且无法动态注入证书路径。
- 必须把证书路径写死进 DSN(不推荐,但现实可行):
sqlsrv:server=...;Encrypt=yes;TrustServerCertificate=no;CaCertPath=/var/www/cert/microsoft-root.crt; - 但 PDO_SQLSRV 扩展本身不解析
CaCertPath—— 这是伪需求。真实生效方式是:将证书合并进系统 CA 包(update-ca-certificates)或设置环境变量SSL_CERT_FILE=/var/www/cert/microsoft-root.crt - 更稳妥的做法:升级到 TP6。TP5 对 Azure SQL 的 SSL 支持本质上是“碰运气”,一旦证书更新或 TLS 版本收紧,连接就会静默降级或中断
验证连接是否真加密
别只看连接成功与否。执行查询后,立刻查 SQL Server 视图确认加密状态:
SELECT encrypt_option FROM sys.dm_exec_connections WHERE session_id = @@SPID;
返回值必须是 TRUE。如果返回 FALSE 或空,说明 SSL 未启用,可能是 DSN 拼写错误(比如写成 encrypt=yes 小写)、证书路径不可读、或 OpenSSL 版本太旧不支持 TLS 1.2。
最容易被忽略的是:Azure SQL 默认拒绝 TLS 1.0/1.1,而某些旧版 PHP(如 7.2 以下)或 OpenSSL(1.0.2 之前)无法协商 TLS 1.2,此时即使证书正确,连接也会被服务器直接断开,错误日志可能只显示“connection refused”而非明确的 SSL 错误。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











