美好的一天, 我正在尝试使用 Windows 身份验证从运行 Python 的 Linux 主机连接到 MS SQL 服务器数据库。
MS SQL服务器托管在运行Windows Server 2012 R2 Standard的机器上,版本为SQL Server Enterprise (64-bit) 12.0.5579.0.
Linux 主机是一个运行 Ubuntu 20.04 Python 3.9.7 和 pyodbc 40.030.
的 Docker 容器使用 SQL 密码身份验证通过 pyodbc 查询数据库成功(所以看起来 ODBC 连接设置正确),但我需要通过我们的域服务器使用 Windows 身份验证在 SQL 服务器上进行身份验证,如此处所述.
我尝试运行
kinit <user>@<domain>
,它询问我的密码(我在那里插入了我的 Windows Active Directory 密码)。
当我尝试检查生成的票证时,我得到:
$ klist
Ticket cache: FILE:/tmp/krb5cc_1001
Default principal: <user>@<domain>
Valid starting Expires Service principal
02/23/23 12:56:26 02/23/23 22:56:26 krbtgt/<domain>@<domain>
renew until 02/24/23 12:56:21
所以它看起来像是生成了一张票并且是有效的。 我还创建了一个
/etc/krb5.conf
文件,开头为:
[libdefaults]
default_realm = <domain>
[...]
但是,当我运行 python 时,我尝试使用命令建立连接
>>> import pyodbc
>>> pyodbc.connect('driver={ODBC Driver 17 for SQL Server};server=<sql_server_name>;DATABASE=<db_name>;Trusted_Connection=Yes;TrustServerCertificate=Yes')
我收到错误信息:
pyodbc.Error: ('HY000', '[HY000] [Microsoft][ODBC Driver 17 for SQL Server]SSPI Provider: Server not found in Kerberos database (851968) (SQLDriverConnect)')
我错过了什么?我怎么知道问题出在我的主机配置还是服务器配置上?
谢谢!
已解决的问题:按照@Charlieface 的建议,在(重新)注册服务主体名称后,我能够通过 Kerberos 进行身份验证,并在 here 中进行了描述。 我使用的语法是:
setspn -S MSSQLSvc/<server>.<domain>:<instance> <domain>\<SQL service account>
.
2个重要细节:
Windows return code: 0x2098<c/> state: 15.
),并使用正确的 SQL 服务帐户(可以通过运行 SELECT service_account FROM sys.dm_server_services
来检查)setspn -S <server>
没有列出所有 SPN,因此由于存在重复项,我无法添加新的 SPN。我不得不使用-Q
的setspn
标志来检查已经存在的“MSSQLSvc”SPN,用setspn -D <spn>
删除它们然后运行命令来注册我需要的SPN。再次感谢@Charlieface!
您的问题是服务主体名称 (SPN) 没有为 SQL Server 注册,因此 Kerberos 协商失败。 Kerberos 是 Windows 身份验证的基础:您的本地 Windows 会话持有 Kerberos TGT 票证,并用于获取 SQL 服务的 TGS 票证。如果服务未注册,则不会发生这种情况。
SQL Server如果有权限会自动注册。您可以像现在一样手动注册它们,但自动注册通常更容易。
这个过程完全记录.
要授予 SQL Server 启动帐户注册和修改 SPN 的权限,请执行以下操作:
- 在域控制器机器上,启动Active Directory 用户和计算机。
- 选择 View > Advanced.
- 在 Computers 下,找到 SQL Server 计算机,然后右键单击并选择 Properties。
- 选择安全选项卡并单击高级。
- 在列表中,如果未列出 SQL Server 启动帐户,请单击 Add 添加它,添加后执行以下操作:
- 选择账户并点击编辑。
- 在Permissions下选择Validated Write servicePrincipalName.
- 向下滚动并在Properties下选择:
读取服务PrincipalName
写servicePrincipalName- 点击OK两次。
- 关闭Active Directory 用户和计算机.
请注意,如果 SQL Server 在本地服务帐户下运行,可能很难使其正常工作。您可能希望在 Managed Service Account 下进行设置。