Microsoft Entra ID 通过 mssql-python 驱动为 Azure SQL 数据库、Azure SQL 托管实例 和 Microsoft Fabric 中的 SQL 数据库提供基于身份的认证。 Microsoft Entra 认证在 SQL 认证基础上提供了以下功能:
- 通过 Microsoft Entra ID 实现集中式身份管理。
- 基于令牌的认证,无需密码。
- 支持条件访问策略。
- Azure托管应用的管理身份。
mssql-python驱动支持七种Microsoft Entra认证模式,均通过Authentication连接字符串关键字进行配置。
身份验证模式
将连接字符串中的 Authentication 关键字设置为以下值之一:
| 认证值 | 描述 |
|---|---|
ActiveDirectoryDefault |
使用 DefaultAzureCredential,自动尝试多种方法。 |
ActiveDirectoryInteractive |
基于浏览器的交互式登录。 |
ActiveDirectoryDeviceCode |
在https://microsoft.com/devicelogin处输入代码。 |
ActiveDirectoryPassword |
使用 Microsoft Entra ID 的用户名和密码 荒废的。 |
ActiveDirectoryMSI |
管理身份(系统分配或用户分配)。 |
ActiveDirectoryServicePrincipal |
服务负责人,附有客户ID和秘密信息。 |
ActiveDirectoryIntegrated |
Windows 集成于 Microsoft Entra ID(Kerberos)。 |
注释
ActiveDirectoryDefault、ActiveDirectoryInteractive 和 ActiveDirectoryDeviceCode 模式需要 azure-identity 软件包。 使用 pip install azure-identity 安装它。
DefaultAzureCredential
该ActiveDirectoryDefault模式使用 Azure Identity SDK 中的DefaultAzureCredential,它会按顺序尝试以下身份验证方法:
- 环境变量。
- 适用于 Kubernetes 的工作负载身份
- 托管身份。
- Azure CLI 凭据
- Azure PowerShell 凭据
- Azure 开发人员 CLI 凭据
- 交互式浏览器(如果已启用)。
示例:默认认证
以下示例连接到 ActiveDirectoryDefault,它使用 DefaultAzureCredential 链自动查找有效凭据:
import mssql_python
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryDefault;"
"Encrypt=yes;"
)
cursor = conn.cursor()
cursor.execute("SELECT USER_NAME()")
print(f"Connected as: {cursor.fetchval()}")
本地开发时使用此模式,因为它会自动获取 Azure CLI 凭证。 对于生产环境,请使用特定的认证模式(ActiveDirectoryMSI, ActiveDirectoryServicePrincipal)。
DefaultAzureCredential 每次第一次连接都会经过多个凭证提供者,这会增加生产工作负载不需要的延迟。
交互式身份验证
对于交互式应用,使用基于浏览器的认证。 用户必须拥有一个使用CREATE USER [user@domain.com] FROM EXTERNAL PROVIDER创建的数据库账户。 完整前提条件请参见配置 Microsoft Entra 认证。
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryInteractive;"
"Encrypt=yes;"
)
在 Windows 上,该模式委托给 ODBC 驱动程序的原生交互流程。 在其他平台上,它使用Azure Identity SDK的浏览器认证。
设备代码身份验证
对于没有浏览器的环境,如SSH会话或容器,使用设备代码认证。 用户必须拥有一个使用 CREATE USER [user@domain.com] FROM EXTERNAL PROVIDER 创建的数据库账户。 关于前置条件,请参见配置 Microsoft Entra 认证。
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryDeviceCode;"
"Encrypt=yes;"
)
# Output: To sign in, use a web browser to open https://microsoft.com/devicelogin
# and enter the code XXXXXXX to authenticate.
按照提示在另一台设备上的浏览器中进行身份验证。
服务主体身份验证
对于不需要用户交互的自动化应用,使用服务主体认证:
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryServicePrincipal;"
"UID=<client-id>;" # Application (client) ID
"PWD=<client-secret>;" # Client secret
"Encrypt=yes;"
)
创建服务主体
- 在 Microsoft Entra ID 注册一个应用程序。
- 创建客户端机密。
- 授予服务负责人对您的数据库的访问权限:
-- In Azure SQL
CREATE USER [app-name] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [app-name];
ALTER ROLE db_datawriter ADD MEMBER [app-name];
Tip
如果CREATE USER因错误33131(显示名称重复)而失败,请使用WITH OBJECT_IDAzure门户(而非应用注册页)的企业应用页面指定服务主体的对象ID:
CREATE USER [app-name] FROM EXTERNAL PROVIDER
WITH OBJECT_ID = '<enterprise-app-object-id>';
托管标识
对于Azure托管的应用,如App Service、Azure Functions和虚拟机,使用管理身份认证:
系统分配的托管标识
使用直接分配给 Azure 资源的身份进行连接:
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryMSI;"
"Encrypt=yes;"
)
用户分配的管理标识
在字段 UID 中指定用户分配的管理身份的客户端ID:
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryMSI;"
"UID=<managed-identity-client-id>;"
"Encrypt=yes;"
)
配置数据库访问
在你的数据库中授予托管身份访问权限。 在创建外部用户之前,必须在服务器上配置 Microsoft Entra 管理员。 要在您的 Azure 资源上启用托管身份,请参见 Azure 资源的托管身份。
-- Replace 'my-app-service' with your Azure resource name
CREATE USER [my-app-service] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [my-app-service];
ALTER ROLE db_datawriter ADD MEMBER [my-app-service];
密码认证(已弃用)
Important
Microsoft SQL 驱动程序中弃用 ActiveDirectoryPassword 身份验证选项(Microsoft Entra ID密码身份验证)。 此高风险身份验证流与强制Microsoft Entra多重身份验证(MFA)不兼容,在强制实施 MFA 的租户中可能不起作用。 计划迁移到其他Microsoft Entra身份验证方法。
Microsoft Entra ID密码身份验证基于 OAuth 2.0 资源所有者密码凭据(ROPC)授予,允许应用程序直接处理其密码来登录用户。
Microsoft建议不要使用 ROPC 流,因为它与 MFA 不兼容。 在大多数情况下,可以使用我们建议的更安全的替代方案。 此流要求在应用程序中高度信任,并且存在在其他流中不存在的风险。 仅当更安全的流不可行时,才使用此流。 Microsoft正远离此高风险身份验证流,以保护用户免受恶意攻击。 有关详细信息,请参阅 规划 Azure 的强制多重身份验证。
如果登录时有用户在场,请使用 ActiveDirectoryInteractive 或 ActiveDirectoryIntegrated 身份验证,以便审核跟踪记录归属于已登录用户,并使条件访问策略生效。
对于无人值守的服务到服务场景,请遵循Microsoft Entra 服务帐户指南:
- 如果应用程序在Azure基础结构上运行,请使用 ActiveDirectoryMSI(或某些驱动程序中的 ActiveDirectoryManagedIdentity)。 托管标识消除了维护和轮换机密和证书的开销。
- 如果托管标识不可用(例如,应用程序在 Azure 外部运行),请使用 ActiveDirectoryServicePrincipal。 在驱动程序支持的情况下,应优先使用客户端证书,而非客户端机密。 使用证书时,私钥会保留在客户端上,并且仅将签名断言发送到Microsoft Entra对客户端进行身份验证。 如果密钥存储在硬件(如 TPM 或 HSM)中,或者被标记为不可导出,就无法像客户端密码那样以字符串形式将其复制出来。
- 不要使用Microsoft Entra用户帐户作为服务帐户。
当你需要用Microsoft Entra账户注册用户名和密码时,请使用密码认证。 用户必须拥有使用 CREATE USER [user@domain.com] FROM EXTERNAL PROVIDER 创建的数据库账户:
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryPassword;"
"UID=<login@domain.com>;"
"PWD=<password>;"
"Encrypt=yes;"
)
Windows集成认证
对于带有Kerberos的域连接Windows环境,请使用Windows集成认证。 此模式要求您的 本地 Active Directory 与 Microsoft Entra ID 联合,并在服务器上配置 Microsoft Entra 管理员:
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryIntegrated;"
"Encrypt=yes;"
)
该模式使用当前 Windows 用户的 Kerberos 凭证。 在 Linux 和 macOS 上,您必须手动配置 Kerberos(krb5.conf 以及有效的 keytab 文件或票证)。 关于客户端Kerberos的设置,请参见“在Linux 上的 SQL Server上使用Active Directory认证”。
访问令牌身份验证
你可以通过外部获取代币,比如通过自定义代币提供者或共享代币缓存。 在这些情况下,使用 SQL_COPT_SS_ACCESS_TOKEN 并通过 attrs_before 参数直接传递令牌。 这种方法绕过了驱动内置的代币获取流程。
import mssql_python
from azure.identity import DefaultAzureCredential
import struct
def get_token():
credential = DefaultAzureCredential(
exclude_interactive_browser_credential=False
)
token_bytes = credential.get_token(
"https://database.windows.net/.default"
).token.encode("utf-16le")
token_struct = struct.pack(
f'<I{len(token_bytes)}s', len(token_bytes), token_bytes
)
return token_struct
SQL_COPT_SS_ACCESS_TOKEN = 1256
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;",
attrs_before={SQL_COPT_SS_ACCESS_TOKEN: get_token()}
)
Important
使用SQL_COPT_SS_ACCESS_TOKEN时,连接字符串 不得包含 UID、 PWD、 Authentication或 Trusted_Connection。 令牌本身负责身份验证。
选择身份验证模式
| Scenario | 建议的模式 |
|---|---|
| 开发机器 |
ActiveDirectoryDefault(使用 Azure CLI) |
| Azure 应用服务 / 函数 |
ActiveDirectoryMSI (比默认更快) |
| Azure Kubernetes 服务 |
ActiveDirectoryDefault (工作负载标识) |
| 本地部署的自动化脚本 | ActiveDirectoryServicePrincipal |
| 交互式桌面应用 | ActiveDirectoryInteractive |
| 没有浏览器的SSH/容器 | ActiveDirectoryDeviceCode |
Troubleshoot
“用户 'NT AUTHORITY\ANONYMOUS LOGON' 登录失败”
验证用户或托管身份是否存在于数据库中:
CREATE USER [identity-name] FROM EXTERNAL PROVIDER;
“AADSTS700016:未找到应用”
服务负责人或应用ID不正确。 核实客户端ID,并且该应用是否已注册在你的Microsoft Entra租户中。
“托管身份端点无法访问”
- 验证已在 Azure 资源上启用托管身份。
- 对于用户分配的身份,请确认客户端ID是否正确。
- 检查该资源是否对身份端点有网络访问权限。
令牌获取超时
ActiveDirectoryDefault 使用 DefaultAzureCredential,它会按顺序遍历凭据提供程序链,直到其中一个成功。 这种链游会在第一个连接时增加几秒的延迟,尤其是在链中较早的提供者(环境变量、工作负载身份)在到达有效连接前失败时。 在生产环境中,直接指定凭据类型以跳过凭据链:
# Slow: DefaultAzureCredential tries multiple providers
conn = mssql_python.connect(connection_string, authentication="ActiveDirectoryDefault")
# Fast: Skip directly to managed identity
conn = mssql_python.connect(connection_string, authentication="ActiveDirectoryMSI")