Laravel8.74 ODBC18连接MSSQL11 TrustServerCertificate配置报错问题
运行环境:
- CloudLinux 9
- Laravel 8.74
- MSSQL 11
- ODBC Driver 18 for SQL Server
配置config/database.php中的sqlsrv连接时,无法正确传入TrustServerCertificate、Encryption参数,连接MSSQL抛出如下错误:
SQLSTATE[08001]: [Microsoft][ODBC Driver 18 for SQL Server]SSL Provider: [error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed:self signed certificate]
初始未加证书相关参数的配置如下:
'000002' => [ 'driver' => 'sqlsrv', 'odbc_driver' => '{ODBC Driver 18 for SQL Server}', 'host' => 'WWW.XXX.YYY.ZZZ', 'database' => 'database_name', 'username' => 'user_name', 'password' => 'pass_word', 'port' => '1433', 'prefix' => '', 'charset' => 'utf8', ]
原生PDO在DSN中加入TrustServerCertificate=1参数可以正常连接,测试代码如下:
<?php $host = "WWW.XXX.YYY.ZZZ"; $user = "user_name"; $password = "pass_word"; $dbname="database_name"; $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_CASE => PDO::CASE_NATURAL, PDO::ATTR_ORACLE_NULLS => PDO::NULL_EMPTY_STRING ]; try { $connection = new PDO("sqlsrv:Server=$host,1433; Database=$dbname;TrustServerCertificate=1", $user, $password); } catch(PDOException $e) { die("Database connection failed: " . $e->getMessage()); exit; } echo"Connection Successful"; ?>
此前尝试在配置根层级添加多种命名格式、多种值类型的TrustServerCertificate、trust_server_certificate参数(值试过1、'1'、'true'、true)都无法解决报错,核心疑问:
- 这类连接参数是否需要放在options数组下?
- ODBC 18驱动对应的Laravel正确配置写法是什么?
核心原因
ODBC Driver 18 for SQL Server默认强制开启SSL加密,且默认校验服务端SSL证书合法性,连接使用自签名证书的MSSQL实例时,必须传入TrustServerCertificate=true跳过证书校验,否则就会抛出证书验证失败的错误。
Laravel 8.x的sqlsrv连接器不会自动识别驼峰命名的ODBC参数,也不会从options数组中读取DSN拼接参数,直接写驼峰格式的参数名、把参数塞到options数组里都不会生效。
正确配置方法
这类ODBC专有DSN参数不需要放在options数组下(options数组仅用于传入PDO原生属性,比如PDO::ATTR_ERRMODE这类常量),直接在连接配置根层级用蛇形命名添加对应参数即可,完整正确配置如下:
'000002' => [ 'driver' => 'sqlsrv', 'odbc_driver' => '{ODBC Driver 18 for SQL Server}', 'host' => 'WWW.XXX.YYY.ZZZ', 'database' => 'database_name', 'username' => 'user_name', 'password' => 'pass_word', 'port' => '1433', 'prefix' => '', 'charset' => 'utf8', // ODBC 18 必须添加的两个参数 'trust_server_certificate' => true, 'encrypt' => true, ]
注意事项
- 参数名必须使用全小写蛇形格式
trust_server_certificate、encrypt,不要使用驼峰格式,Laravel的连接器无法识别驼峰命名的配置键 - 参数值直接传布尔值
true即可,不需要传字符串、数字格式的值,Laravel内部会自动将布尔值转换为ODBC驱动识别的Yes标识拼入DSN - 修改完配置后必须执行
php artisan config:clear清除配置缓存,若之前执行过php artisan config:cache缓存配置,新配置不会自动加载生效。
内容的提问来源于stack exchange,提问作者zehyr

