使用pyodbc从Linux到Windows SQL Server进行身份验证

Ess*_*420 6 python sql linux windows pyodbc

我正在尝试使用pyodbc从Linux机器连接到Windows SQL Server。

我确实有两个限制:

  • 需要使用Windows域帐户登录
  • 需要使用python3
  • 需要从Linux到Windows
  • 需要连接到特定实例

我按照Microsoft的说明设置了环境并使其正常工作(我可以导入pyodbc并使用已配置的贻贝驱动程序)。

我不熟悉Windows域身份验证,而其他方面则不熟悉,所以这里就是我的问题所在。

我的连接字符串:

DRIVER={ODBC Driver 17 for SQL Server};SERVER=myserver.mydomain.com;PORT=1433;DATABASE=MyDatabase;Domain=MyCompanyDomain;Instance=MyInstance;UID=myDomainUser;PWD=XXXXXXXX;Trusted_Connection=yes;Integrated_Security=SSPI
Run Code Online (Sandbox Code Playgroud)

假设应该使用“ Trusted_Connection”来使用Windows域身份验证,而不是直接通过SQL Server进行身份验证。

我在运行pyodbc.connect(connString)遇到的错误:

pyodbc.Error: ('HY000', '[HY000] [unixODBC][Microsoft][ODBC Driver 17 for SQL Server]SSPI Provider: No Kerberos credentials available (851968) (SQLDriverConnect)')
Run Code Online (Sandbox Code Playgroud)

我从其他来源了解到,此代码应在Windows上运行,因为此代码将使用当前登录用户的凭据。

我的问题是如何使用Windows域凭据从Linux连接到Windows SQL Server实例。

ben*_*kah 9

您必须获得 Kerberos 票证才能执行此操作。您的示例没有指定您的 Linux 系统是否设置为通过 Kerberos 进行身份验证,或者您之前是否在代码命中连接字符串之前获得了 Kerberos 票证。

如果您的 Linux 系统设置为通过 Kerberos 进行身份验证,那么作为概念证明,您可以从命令行使用 kinit 获取 Kerberos 票证。这是通过 WSL 在 Windows 上的 Ubuntu 中运行的 python3 中对我有用的方法。蟒蛇代码:

#!/usr/bin/env python

# minimal example using Kerberos auth
import sys
import re
import pyodbc

driver='{ODBC Driver 17 for SQL Server}'
server = sys.argv[1]
database = sys.argv[2]

# trusted_connection uses kerberos ticket and ignores UID and PASSWORD in connection string
# https://docs.microsoft.com/en-us/sql/connect/odbc/linux-mac/using-integrated-authentication?view=sql-server-ver15

try:
    cnxn = pyodbc.connect(driver=driver, server=server, database=database, trusted_connection='yes')
    cursor = cnxn.cursor()
except pyodbc.Error as ex:
    msg = ex.args[1]
    if re.search('No Kerberos', msg):
        print('You must login using kinit before using this script.')
        exit(1)
    else:
        raise

# Sample select query
cursor.execute("SELECT @@version;")
row = cursor.fetchone()
while row:
    print(row[0])
    row = cursor.fetchone()
print('success')
Run Code Online (Sandbox Code Playgroud)

如果您没有票,这会告诉您。由于它使用票证,因此您不必在脚本中指定用户或密码。它会忽略两者。

现在我们运行它:

user@localhost:~# kdestroy # make sure there are no active tickets
kdestroy: No credentials cache found while destroying cache

user@localhost:~# python pyodbc_sql_server_test.py tcp:dbserver.example.com mydatabase
You must login using kinit before using this script.

user@localhost:~# kinit
Password for user@DOMAIN.LOCAL:

user@localhost:~# python pyodbc_sql_server_test.py tcp:dbserver.example.com mydatabase
Microsoft SQL Server 2016 (SP2-GDR) (KB4505220) - 13.0.5101.9 (X64)
        Jun 15 2019 23:15:58
        Copyright (c) Microsoft Corporation
        Enterprise Edition (64-bit) on Windows Server 2016 Datacenter 10.0 <X64> (Build 14393: )

success

user@localhost:~#
Run Code Online (Sandbox Code Playgroud)

您也可能成功地从在建立此连接之前运行的 python 代码获取 Kerberos 票证,但这超出了本答案的范围。搜索 python Kerberos 模块可能会为您指明解决方案。

似乎还可以设置 Linux 系统,以便在用户登录后立即自动获取可以传递给其他进程的 Kerberos 票证。这也超出了本答案的范围,但在 Linux 登录时搜索自动 Kerberos 票证可能会产生一些线索。


小智 7

我为同一任务找到了两种方法。我有带 AD 身份验证的 MSSQL 服务器。

您可以使用 JVM。加载并安装 JAVA https://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html。还要安装 JPype1 版本 0.6.3 pip install JPype==0.6.3。0.6.3 以上的版本无法正常工作

import jaydebeapi
import pandas as pd
driver_name = "net.sourceforge.jtds.jdbc.Driver"
connection_url="jdbc:jtds:sqlserver://<server>:<port>/<database name>"
connection_properties = {
"domain": "<domain name>",
"user": "<username>",
"password": "<pwd>"}
jar_path =  <path to jsds>"/jtds-1.3.1.jar"
CONN = jaydebeapi.connect(driver_name, connection_url, connection_properties, jar_path)
sql = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS"
df = pd.read_sql(sql, CONN)
Run Code Online (Sandbox Code Playgroud)

这个版本对我来说太慢了。

您也可以通过 FreeTDS使用pyodbc。创建 FreeTDS 连接 在 Linux 上安装FreeTDS,像这样apt-get install tdsodbc freetds-bin配置FreeTDS /etc/odbcinst.ini

[FreeTDS]
Description=FreeTDS
Driver=/usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so
Setup=/usr/lib/x86_64-linux-gnu/odbc/libtdsS.so
Run Code Online (Sandbox Code Playgroud)

并打开它 odbcinst -i -d -f /etc/odbcinst.ini

之后,您可以使用pyodbc

import pandas as pd
import pyodbc    
CONN =pyodbc.connect('DRIVER={FreeTDS};'
                                  'Server=<server>;'
                                  'Database=<database>;'
                                  'UID=<domain name>\\<username>;'
                                  'PWD=<password>;'
                                  'TDS_Version=8.0;'
                                  'Port=1433;')
sql = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS"
df = pd.read_sql(sql, CONN)
Run Code Online (Sandbox Code Playgroud)

它的工作速度要快得多


Ess*_*420 5

我最终使用了pymssql库,该库基本上是FreeTDS驱动程序之上的pyodbc。它开箱即用。

很奇怪我很难找到这个库。

  • 不幸的是 pymssql 项目已停止,您应该考虑使用 pyodbc (3认同)
  • 如项目页面所述:“Recent Changes Version 2.1.5 - 2020-09-17 - Mikhail Terekhov General Revert deprecation”来源:https://pypi.org/project/pymssql/ 这确实是此问题的最佳答案。 (3认同)