本地用Azure托管身份连接Azure SQL遇<token-identified principal>登录失败
我来帮你一步步解决本地调试时,托管身份连接Azure SQL的认证问题,咱们从环境配置到代码调整逐一排查:
一、先搞定本地环境的托管身份权限配置
本地运行时,没法直接用App Service的系统托管身份,得靠你的Azure AD账户(或者专门的服务主体)来完成认证,先把权限捋清楚:
步骤1:确认本地Azure账户登录正确
打开Azure CLI,执行az login登录有权访问目标Azure SQL和Key Vault的账户;如果有多个订阅,别忘了切换到对应订阅:az account set --subscription <你的订阅ID>。要是你用Visual Studio/Rider开发,也确保IDE里登录的是同一个账户。步骤2:给你的Azure AD账户配置Azure SQL权限
先暂时用SQL管理员账号(密码登录)打开SSMS,连接到你的Azure SQL服务器,执行下面的SQL语句,把你的AD账户添加为数据库用户并赋予必要权限:-- 替换成你的Azure AD邮箱 CREATE USER [your-aad-email@domain.com] FROM EXTERNAL PROVIDER; -- 读写权限根据实际需求调整 ALTER ROLE db_datareader ADD MEMBER [your-aad-email@domain.com]; ALTER ROLE db_datawriter ADD MEMBER [your-aad-email@domain.com]; -- 如果需要EF迁移权限,再加db_owner或者对应的角色 ALTER ROLE db_owner ADD MEMBER [your-aad-email@domain.com];要是你的账户本身就是Azure SQL服务器的AD管理员,这一步可以直接跳过。
步骤3:验证Key Vault的访问权限
登录Azure门户找到你的Key Vault,进入「访问策略」页面,确认你的Azure AD账户有Secrets Get权限——毕竟咱们要从Key Vault里读连接字符串对吧?
二、调整代码适配本地托管身份认证
你当前用的是旧版的Azure身份认证库,咱们换成更灵活的新版,同时确保连接字符串支持AD认证:
1. 更新NuGet包
先把旧包换掉:移除Microsoft.Azure.KeyVault和Microsoft.Azure.Services.AppAuthentication,安装Azure.Identity和Azure.Security.KeyVault.Secrets这两个新版包。
2. 修改Key Vault初始化代码
把Program.cs里原来的Key Vault配置代码改成下面这样:
var keyVaultEndpoint = builder.Configuration.GetSection("KeyVault").GetValue<string>("VaultURI"); if (!string.IsNullOrEmpty(keyVaultEndpoint)) { builder.Configuration.AddAzureKeyVault( new Uri(keyVaultEndpoint), new DefaultAzureCredential()); }
DefaultAzureCredential会自动适配本地环境——优先用Azure CLI登录的账户、IDE登录的账户,不用手动指定认证方式,比旧的AzureServiceTokenProvider省心多了。
3. 确保连接字符串格式正确
不管你的连接字符串存在Key Vault还是appsettings.json里,都要改成不带用户名密码的格式,重点加上Authentication=Active Directory Default;:
Server=tcp:<你的SQL服务器名>.database.windows.net,1433;Database=<数据库名>;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;Authentication=Active Directory Default;
这个参数会告诉EF Core自动用托管身份(本地就是你的AD账户)去认证Azure SQL。
三、本地调试验证
先测试SSMS连接
打开SSMS,服务器名称填你的Azure SQL地址,身份验证选「Azure Active Directory - 通用且带有MFA支持」,输入你的AD邮箱登录。如果能成功连接,说明SQL端的AD身份配置没问题。调试API项目
启动调试后,调用需要访问数据库的接口,看看还会不会出现<token-identified principal>登录失败的错误。要是还报错,可以加一段代码打印令牌信息,确认令牌受众是不是Azure SQL(https://database.windows.net/):var credential = new DefaultAzureCredential(); var token = await credential.GetTokenAsync(new Azure.Core.TokenRequestContext(new[] { "https://database.windows.net/.default" })); Console.WriteLine($"令牌受众: {token.Token}"); Console.WriteLine($"令牌过期时间: {token.ExpiresOn}");
四、提前为容器部署到App Service做准备
等本地调试通了,部署到App Service也很简单:
- 打开App Service的「身份」页面,开启「系统分配」的托管身份;
- 回到Azure SQL,执行SQL语句给这个系统托管身份加数据库权限:
CREATE USER [你的App Service名称] FROM EXTERNAL PROVIDER;,再赋予对应的读写/迁移权限; - 给这个系统托管身份配置Key Vault的访问策略;
- 连接字符串还是用刚才的格式,App Service会自动用系统托管身份完成认证,不用改代码。
内容的提问来源于stack exchange,提问作者Jean-François Beaulieu

