代码之家  ›  专栏  ›  技术社区  ›  Esser420

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

  •  23
  • Esser420  · 技术社区  · 7 年前

    我正在尝试使用pyodbc从linux计算机连接到windows SQL Server。

    我确实有几个限制:

    • 需要使用windows域帐户登录
    • 需要使用python3
    • 需要从Linux到Windows执行此操作
    • 需要连接到特定实例

    我按照microsoft的描述设置了环境并使其正常工作(我可以导入pyodbc并使用配置的mussel驱动程序)。

    我不熟悉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
    

    应该使用“Trusted\u Connection”来使用Windows域身份验证,而不是直接使用SQL server进行身份验证。

    运行时出现的错误 pyodbc。连接(connString) :

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

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

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

    5 回复  |  直到 7 年前
        1
  •  10
  •   benrifkah    5 年前

    您必须获得Kerberos票证才能使其工作。您的示例没有指定是将Linux系统设置为通过Kerberos进行身份验证,还是在代码命中连接字符串之前已获得Kerberos票证。

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

    #!/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')
    

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

    现在我们运行它:

    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:~#
    

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

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

        2
  •  8
  •   Esser420    7 年前

    我最终使用了pymssql库,它基本上是FreeTDS驱动程序之上的pyodbc。它是现成的。

    奇怪的是,我怎么这么难找到这个图书馆。。

        3
  •  7
  •   Nikolai Kamenskiy    5 年前

    我为同一项任务找到了两种方法。我有一个带有AD auth的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)
    

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

    您还可以使用 通过FreeTDS的pyodbc 。要创建FreeTDS连接,请在Linux上安装FreeTDS apt-get install tdsodbc freetds-bin ,配置FreeTDS /etc/ODB安装。ini公司 像这样:

    [FreeTDS]
    Description=FreeTDS
    Driver=/usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so
    Setup=/usr/lib/x86_64-linux-gnu/odbc/libtdsS.so
    

    然后打开它 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)
    

    它的工作速度快得多

        4
  •  3
  •   Nick Green    4 年前

    我试图做同样的事情,在阅读了OPs的答案后,我测试了pymssql,并注意到它只适用于以下内容:

    pymssql.connect(server='myserver', user='domain\username', password='password', database='mydb')
    

    意识到这就是pymssql所需的全部内容后,我回到pyodbc,并能够使用它:

    pyodbc.connect("DRIVER={FreeTDS};SERVER=myserver;PORT=1433;DATABASE=mydb;UID=domain\username;PWD=password;TDS_Version=8.0")
    

    我只是想感谢你发布这篇文章,因为它对我帮助很大!!!!:)

        5
  •  0
  •   QA Collective    6 年前

    通过Linux生成windows身份验证非常复杂。EasySoftDB(商业版)曾经能够处理这个问题,FreeTDS有一些复杂的支持。

    https://docs.microsoft.com/en-us/sql/connect/odbc/linux-mac/using-integrated-authentication

    我的建议是不要使用Windows身份验证,而是使用SQL身份验证。实际上,除了在连接字符串中提供用户名和密码之外,没有任何安全性差异。但这会让你的生活轻松很多。