在预连接参数中将Azure SQL DB的Azure AD令牌传递给SQLAlchemy create_engine() [英] Pass Azure AD Token for Azure SQL DB in pre-connection arguments to SQLAlchemy create_engine()

查看:109
本文介绍了在预连接参数中将Azure SQL DB的Azure AD令牌传递给SQLAlchemy create_engine()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过带有AD令牌的SQLAlchemy连接到Azure SQL数据库.

I'm wanting to connect to an Azure SQL DB via SQLAlchemy with an AD token.

我已遵循 https://github.com/felipefandrade/azuresqlspn 并可以成功连接用这种方法.但是,我想扩展它并使用SQLAlchemy来管理连接.

I've followed https://github.com/felipefandrade/azuresqlspn and can successfully connect with this method. However, I want to extend this and use SQLAlchemy to manage the connection.

from os import environ
import struct
import adal
from sqlalchemy import create_engine
import pyodbc

clientSecret = environ.get('clientSecret')
clientID = environ.get('clientID')
tenantID =  environ.get('tenantID')
authorityHostUrl = "https://login.microsoftonline.com"
authority_url = authorityHostUrl + '/' + tenantID
resource = "https://database.windows.net/"
context = adal.AuthenticationContext(authority_url, api_version=None)

token = context.acquire_token_with_client_credentials(
    resource,
    clientID,
    clientSecret)


tokenb = bytes(token["accessToken"], "UTF-8")
exptoken = b''

for i in tokenb:
    exptoken += bytes({i})
    exptoken += bytes(1)

tokenstruct = struct.pack("=i", len(exptoken)) + exptoken

driver = "Driver={ODBC Driver 17 for SQL Server}"
server = ";SERVER={0}".format(environ.get('server'))
database = ";DATABASE={0}".format(environ.get('database'))

connString = driver + server + database

SQL_COPT_SS_ACCESS_TOKEN = 1256
conn = pyodbc.connect(connString, attrs_before={SQL_COPT_SS_ACCESS_TOKEN:tokenstruct})

cursor = conn.cursor()
cursor.execute("SELECT TOP 20 ID, Name FROM [Table1]")
row = cursor.fetchone()
print("######")
print("Using pyodbc directly - This works")
while row:
    print (str(row[0]) + " " + str(row[1]))
    row = cursor.fetchone()

print("#####")
print("Connecting via sqlalchemy - This doesn't work")
SAconnString = "mssql+pyodbc://<server>.database.windows.net/<database>?driver=ODBC+Driver+17+for+SQL+Server"
db = create_engine(SAconnString, connect_args={'attrs_before': {SQL_COPT_SS_ACCESS_TOKEN:tokenstruct}})

SAconn = db.connect()
result = SAconn.execute("SELECT TOP 20 ID, Name FROM [Table1]")
for row in result:
    print(row['ID'] + " " + row['Name'])

如代码中所述,

将可以使用pyodbc.connect()方法.但是,使用SQLAlchemy时出现错误FA005] [Microsoft][ODBC Driver 17 for SQL Server]Cannot use Access Token with any of the following options: Authentication, Integrated Security, User, Password.在我看来,connect_args选项正在传递令牌,但是还有其他选项.如何获得SQLAlchemy正确将AD令牌传递给pyodbc?

As noted in the code, using pyodbc.connect() method will work. However, using SQLAlchemy I get the error FA005] [Microsoft][ODBC Driver 17 for SQL Server]Cannot use Access Token with any of the following options: Authentication, Integrated Security, User, Password. It appears to me the connect_args option is passing the token through, but with other options too. How do I get SQLAlchemy to correctly pass the AD Token to pyodbc?

推荐答案

需要使用urllib显式发送PyODBC连接字符串.

Need to send PyODBC connection string explicitly with urllib.

connString = driver + server + database
params = urllib.parse.quote(connString)
db = create_engine("mssql+pyodbc:///?odbc_connect={0}".format(params), connect_args={'attrs_before': {SQL_COPT_SS_ACCESS_TOKEN:tokenstruct}})

这篇关于在预连接参数中将Azure SQL DB的Azure AD令牌传递给SQLAlchemy create_engine()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆