使用pyodbc连接SQL Server数据库时出现OperationalError错误

4

我正在尝试使用Python 3中的pyodbc连接到SQL服务器数据库。但是,当我尝试建立连接时,出现了错误。

我像这样做:

import pyodbc
conn = pyodbc.connect('Driver={ODBC Driver 18 for SQL Server};Server=192.168.2.250;Database=DB;UID=username;PWD=password;')

我得到了这个:

OperationalError: ('08001', '[08001] [Microsoft][ODBC Driver 18 for SQL Server]SSL Provider: [error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocol][error:140B40C7:SSL routines:SSL_do_handshake:peer did not return a certificate] (-1) (SQLDriverConnect)')

有人知道如何解决这个问题吗?数据库不是我自己的,所以希望有一种解决方案,不需要更改任何设置。

我在Windows Subsystem for Linux中运行Ubuntu。


你连接的是哪个版本的SQL Server?错误信息表明它可能是一个非常旧的版本,或者没有安装服务包或累积更新,如果它不支持TLS 1.2 - 那就是ssl_choose_client_version:unsupported protocol告诉你的。如果你无法更新远程服务器,那么你需要查看是否可以在WSL中的OpenSSL cnf文件中启用TLS 1.1支持。TLS 1.0和TLS 1.1在现代堆栈中默认禁用(有时甚至未编译),因为它们被认为是不安全的。 - AlwaysLearning
SQL Server版本:Microsoft SQL Server 2008(SP4)-10.0.6241.0(Intel X86)Apr 17 2015 11:02:30版权所有(c)1988-2008 Microsoft Corporation标准版在Windows NT 6.0 <X86>(Build 6002:Service Pack 2)(VM)上运行。我尝试按照此处所述启用TLS 1.0或1.1,但这并没有解决问题。仍然是相同的错误消息。 - kev15
1
SQL Server 2008 SP4 直到 10.0.6547.0 版本才支持 TLS 1.2。您应该与服务器管理员讨论安装 TLS 1.2 更新的事宜。虽然 Microsoft 已经多年不再支持 SQL Server 2008,但您应该敦促他们升级到新的受支持版本。 - AlwaysLearning
即使是旧的加密方式也比没有加密好。更新OpenSSL cnf文件需要一定的方法。请查看我的之前的SO回答,看看是否能帮助您启用TLS 1.1。 - AlwaysLearning
2个回答

4

ODBC Driver 18 for SQL Server有一项重大变更

类似于几年前Web浏览器中的HTTP到HTTPS默认更改(以及它们的安全原因),我们将把Encrypt连接选项的默认值从no更改为yes/mandatory

发布了ODBC Driver 18.0 for SQL Server

因此,这意味着:

conn = pyodbc.connect('Driver={ODBC Driver 18 for SQL Server};Server=192.168.2.250;Database=DB;UID=username;PWD=password;')

是相同的

conn = pyodbc.connect('Driver={ODBC Driver 18 for SQL Server};Server=192.168.2.250;Database=DB;UID=username;PWD=password;Encrypt=yes')

如果您不想要加密连接,必须选择退出:

conn = pyodbc.connect('Driver={ODBC Driver 18 for SQL Server};Server=192.168.2.250;Database=DB;UID=username;PWD=password;Encrypt=no')

我们还改变了TrustServerCertificate的行为,使其不再与Encrypt设置绑定。

因此,如果您的服务器使用自签名证书,则还必须选择退出证书验证。

conn = pyodbc.connect('Driver={ODBC Driver 18 for SQL Server};Server=192.168.2.250;Database=DB;UID=username;PWD=password;Encrypt=no;TrustServerCertificate=yes')

1
这似乎是一个不错的开始。如果我包括 Encrypt=no,错误会变得更短一些:OperationalError: ('08001', '[08001] [Microsoft][ODBC Driver 18 for SQL Server]SSL Provider: [error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocol] (-1) (SQLDriverConnect)')(最后一部分关于 SSL_do_handshake:peer did not return a certificate 的内容已经消失了)。 - kev15
请查看更新后的答案。 - David Browne - Microsoft
1
谢谢,但即使使用 Encrypt=no;TrustServerCertificate=yes,我仍然得到相同的错误。 - kev15
SQL Server 2008 已经停止支持,所以这可能不是一个有效的组合。旧版的ODBC驱动程序仍然可以下载。 - David Browne - Microsoft

0

最终我把我的脚本从WSL中移除了。在Windows下运行相同的命令(使用David的修改或者ODBC Driver 17 for SQL Server代替18)在我的情况下没有任何问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接