SQLAlchemy连接Azure SQL时服务主体Token认证失败报18456错误
问题背景
使用服务主体(Service Principal)+ 访问令牌的认证方式,通过SQLAlchemy搭配pandas.DataFrame.to_sql方法连接Azure SQL数据库执行数据插入操作。当前使用的客户端ID、客户端密钥、租户ID凭据已完成有效性核验:同一套凭据可正常连接同环境下的另一台Azure SQL数据库,且在Azure Databricks中使用该套凭据的连接逻辑已验证可用。但连接目标数据库时抛出如下错误:
sqlalchemy.exc.InterfaceError: (pyodbc.InterfaceError) ('28000', "[28000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Login failed for user '<token-identified principal>'. (18456) (SQLDriverConnect); [28000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Login failed for user '<token-identified principal>'. (18456)")
排查思路
按以下优先级逐一排查:
- 确认目标Azure SQL数据库是否开启Azure Active Directory(AAD)认证:仅支持SQL身份认证的数据库实例无法识别服务主体的令牌身份,会直接返回登录失败。
- 校验服务主体在目标库的独立授权:Azure SQL的数据库级别权限是库级隔离的,服务主体能连接同实例下的其他库,不代表在当前目标库有访问权限,必须单独给目标库做服务主体的用户映射和权限分配。
- 核对访问令牌的申请参数:连接Azure SQL申请令牌时,资源受众(resource/scope)必须固定为
https://database.windows.net/,如果令牌申请时填错资源地址、或者令牌是为其他云资源申请的,目标库无法完成令牌校验。 - 确认租户一致性:检查目标数据库绑定的AAD租户,和凭据所属的租户ID是否一致,跨租户访问场景下即使凭据本身有效,也会被目标库拒绝登录。
- 检查连接串配置准确性:确认连接串中填写的目标实例域名、数据库名完全正确,避免因为配置错误连到其他无权限的数据库实例。
解决方案
对应排查项逐一修复:
- 开启目标库AAD认证
进入目标Azure SQL数据库的Azure门户配置页,找到「Azure Active Directory」设置项,完成AAD管理员配置,开启AAD身份认证入口。 - 为服务主体配置目标库权限
使用AAD管理员账号登录目标数据库,执行以下SQL语句创建服务主体对应的数据库用户,并分配to_sql操作所需的必要权限:
执行完成后等待1-2分钟,等待AAD权限同步完成后再重试连接。-- 替换尖括号内容为AAD中注册的服务主体的显示名称 CREATE USER [<服务主体显示名称>] FROM EXTERNAL PROVIDER; -- 分配数据写入权限,满足数据插入需求 ALTER ROLE db_datawriter ADD MEMBER [<服务主体显示名称>]; -- 分配DDL权限,满足to_sql自动建表需求,若表已提前创建可省略该句 ALTER ROLE db_ddladmin ADD MEMBER [<服务主体显示名称>]; - 修正令牌申请逻辑
申请访问令牌时,将资源参数固定为https://database.windows.net/,不要追加实例名、库名后缀;拿到令牌后不要做额外的截断、转义处理,直接通过pyodbc连接参数的attrs_before字段传入连接上下文。 - 校验连接串配置
参考已经验证可用的数据库连接串,仅修改目标实例域名(格式为<实例名>.database.windows.net)、目标库名两个字段,其余认证参数、ODBC驱动配置(要求ODBC Driver 17及以上版本)保持和可用连接串一致。
内容的提问来源于stack exchange,提问作者Radiatelabs
相关产品推荐
相关产品推荐

