Docker环境下Laravel连接SQL Server出现SSL Provider错误
执行Laravel查询语句DB::connection('sqlsrv')->table('Order')->first();时触发如下错误:
Illuminate\Database\QueryException SQLSTATE[08001]: [Microsoft][ODBC Driver 18 for SQL Server]SSL Provider: [error:0A000086:SSL routines::certificate verify failed:EE certificate key too weak] (Connection: sqlsrv, SQL: select top 1 * from [Order]).
环境为Ubuntu服务器的Docker容器,应用仅本地运行无外部访问,已尝试启用SSL加密、信任服务器证书,在Laravel数据库配置中设置encrypt和trustServerCertificate,但问题未解决。
相关配置
Nginx 配置
server { server_name localhost; root /var/www/html/crm/public/; index index.php index.html index.htm; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; location / { try_files $uri $uri/ /index.php?$query_string; } # PHP-FPM Configuration Nginx location ~ \.php$ { try_files $uri = 404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php8:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param REQUEST_URI $request_uri; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } }
Dockerfile 配置
FROM php:8.2-fpm RUN apt-get update && apt-get upgrade -y RUN apt-get install -y libzip-dev zip unzip git curl gnupg RUN apt-get install -y default-mysql-client RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg RUN curl https://packages.microsoft.com/config/ubuntu/24.04/prod.list | tee /etc/apt/sources.list.d/mssql-release.list RUN apt-get update && ACCEPT_EULA=Y apt-get install -y msodbcsql18 RUN apt-get update RUN apt-get install -y unixodbc-dev \ && pecl install sqlsrv-5.12.0 pdo_sqlsrv-5.12.0 RUN docker-php-ext-enable sqlsrv pdo_sqlsrv RUN docker-php-ext-install zip \ && docker-php-ext-install mysqli \ && docker-php-ext-install bcmath \ && docker-php-ext-install ctype \ && docker-php-ext-install fileinfo \ && docker-php-ext-install pdo \ && docker-php-ext-install pdo_mysql RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
Docker Compose 配置
version: '3.8' services: php8: build: context: ./docker/php8 hostname: php8 ports: - "19000:9000" volumes: - ./projects/:/var/www/html/ - ./docker/php8/www.conf:/usr/local/etc/php-fpm.d/www.conf - ./docker/php8/php.ini:/usr/local/etc/php/php.ini environment: MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD} SQLSRV_ENCRYPT: true SQLSRV_TRUST_SERVER_CERTIFICATE: true SQLSRV_TLS_VERSION: 1.2 networks: - laravel nginx: platform: linux/x86_64 image: nginx:1.13.8 ports: - "80:80" volumes: - ./projects/:/var/www/html/ - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf depends_on: - php8 networks: - laravel mysql: platform: linux/x86_64 image: mysql:8.0 ports: - "3306:3306" depends_on: - php8 environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD} networks: - laravel phpmyadmin: image: phpmyadmin/phpmyadmin:latest platform: linux/x86_64 environment: PMA_HOST: mysql PMA_USER: root PMA_PASSWORD: ${MYSQL_ROOT_PASSWORD} depends_on: - mysql ports: - "8080:80" networks: - laravel networks: laravel: driver: bridge
Laravel 数据库配置(config/database.php)
'sqlsrv' => [ 'driver' => 'sqlsrv', 'url' => env('DB_URL'), 'host' => env('MSSQL_HOST', 'localhost'), 'port' => env('MSSQL_PORT', '1433'), 'database' => env('MSSQL_DATABASE', 'laravel'), 'username' => env('MSSQL_USERNAME', 'root'), 'password' => env('MSSQL_PASSWORD', ''), 'charset' => env('DB_CHARSET', 'utf8'), 'prefix' => '', 'prefix_indexes' => true, // 'encrypt' => env('DB_ENCRYPT', 'yes'), // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'), 'schema' => 'dbo', 'options' => [ PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8, 'encrypt' => false, 'trustServerCertificate' => true, ], ],
解决方案
错误根源是ODBC Driver 18对SSL证书密钥强度要求较高,SQL Server使用的证书密钥长度不足(<2048位)时触发校验失败。结合本地环境,可按以下步骤解决:
修正Laravel配置优先级
Laravel顶层的encrypt和trust_server_certificate配置会覆盖options内的设置,调整配置并通过环境变量控制:'sqlsrv' => [ // ... 其他原有配置 'encrypt' => env('DB_ENCRYPT', 'no'), 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'yes'), 'options' => [ PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8, ], ],在
.env文件中添加:DB_ENCRYPT=no DB_TRUST_SERVER_CERTIFICATE=yes强制指定兼容TLS版本
若需保留加密,可强制指定TLS 1.2规避高版本TLS的密钥强度校验,在options中添加:'options' => [ PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8, PDO::SQLSRV_ATTR_TLS_VERSION => 'TLSv1.2', ],全局调整ODBC Driver配置
在Docker容器中修改ODBC全局配置,降低安全校验级别(仅适用于本地测试环境):
在Dockerfile中追加以下命令:RUN echo "[ODBC Driver 18 for SQL Server]" >> /etc/odbcinst.ini \ && echo "Description=Microsoft ODBC Driver 18 for SQL Server" >> /etc/odbcinst.ini \ && echo "Driver=/opt/microsoft/msodbcsql18/lib64/libmsodbcsql-18.3.so.2.1" >> /etc/odbcinst.ini \ && echo "UsageCount=1" >> /etc/odbcinst.ini \ && echo "Trace=No" >> /etc/odbcinst.ini \ && echo "Encrypt=no" >> /etc/odbcinst.ini \ && echo "TrustServerCertificate=yes" >> /etc/odbcinst.ini替换SQL Server证书(生产环境推荐)
测试环境可使用上述临时方案,生产环境需更换SQL Server的SSL证书为密钥长度≥2048位的合规证书,从根源解决密钥强度不足问题。
内容的提问来源于stack exchange,提问作者enmeydan

