Linux虚拟机用Python连接SQL Server遇SSL证书匹配错误求解决
错误详情
driver:ODBC Driver 18 for SQL Server DRIVER=ODBC Driver 18 for SQL Server;SERVER=ACE2T21978SQ001.az.3pc.att.com;DATABASE=QE2S_LASA01;UID=ITSERVICES\m53132;PWD=Dallastexas+6;Trusted_Connection=yes;TrustedServerCertificate=yes;Encrypt=yes; Traceback (most recent call last): File "python_table_import.py", line 50, in <module> cnxn = pyodbc.connect(con_string) pyodbc.OperationalError: ('08001', '[08001] [Microsoft][ODBC Driver 18 for SQL Server]SSL Provider: [error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed:subject name does not match host name] (-1) (SQLDriverConnect)')
错误原因
ODBC Driver 18 for SQL Server启用加密连接时,会校验SSL证书的**主题名称(Subject Name)或备用主题名称(Subject Alternative Name)**是否与连接的SQL Server主机名一致。你设置的TrustedServerCertificate=yes仅跳过证书链的信任校验,不会跳过主机名匹配校验,因此当证书中的主机名与你指定的SERVER值不匹配时,就会触发该错误。
解决方案
1. 指定证书中的正确主机名(推荐)
在连接字符串中添加HostNameInCertificate参数,值为SQL Server SSL证书中实际包含的主机名(可以是Subject或SAN中的名称)。
修改后的连接字符串示例:
con_string = "DRIVER=ODBC Driver 18 for SQL Server;SERVER=ACE2T21978SQ001.az.3pc.att.com;DATABASE=QE2S_LASA01;UID=ITSERVICES\\m53132;PWD=Dallastexas+6;Trusted_Connection=yes;TrustedServerCertificate=yes;Encrypt=yes;HostNameInCertificate=证书上的实际主机名"
如何获取证书中的主机名
在Linux终端执行以下命令,查看目标SQL Server的证书信息:
openssl s_client -connect ACE2T21978SQ001.az.3pc.att.com:1433 | openssl x509 -noout -subject -ext subjectAltName
输出结果中,subject字段的CN=值就是主题名称,X509v3 Subject Alternative Name字段列出了备用主题名称,选择其中一个填入HostNameInCertificate即可。
2. 临时禁用主机名校验(仅测试环境)
如果是测试环境且不需要严格的安全校验,可以通过调整连接参数来跳过主机名校验:
- 将
Encrypt改为optional(允许非加密连接,不推荐生产环境):DRIVER=ODBC Driver 18 for SQL Server;SERVER=ACE2T21978SQ001.az.3pc.att.com;DATABASE=QE2S_LASA01;UID=ITSERVICES\m53132;PWD=Dallastexas+6;Trusted_Connection=yes;Encrypt=optional;
3. 更新SQL Server证书(生产环境长期方案)
联系SQL Server管理员,将当前连接的主机名ACE2T21978SQ001.az.3pc.att.com添加到证书的备用主题名称(SAN)中,或者更换匹配该主机名的SSL证书。
额外注意点
你当前的连接字符串同时指定了Trusted_Connection=yes和UID/PWD,在Linux下使用Windows集成认证(Kerberos)通常不需要提供密码,建议确认是否需要采用Kerberos认证方式(需提前配置Kerberos客户端)。如果只是使用SQL Server身份认证,应移除Trusted_Connection=yes参数。
内容的提问来源于stack exchange,提问作者Chaithra. m.c

