You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用托管标识Object Id而非UserId连接Azure PostgreSQL

问题描述

我需要一种简洁方式,通过托管标识连接Azure PostgreSQL数据库,同时兼容以下场景:

  • 部署后的应用(Azure Web API、Azure VM)
  • Visual Studio本地开发

目前已实现本地和部署环境获取有效访问令牌并连接数据库,但存在以下问题:

  1. 部署环境中无法从访问令牌自动提取连接字符串所需的UserId值(本地可通过upn claim获取,但云端托管标识的令牌无此claim)
  2. 疑惑为何使用访问令牌时仍需UserId——令牌中包含oid(ObjectId),且数据库通过pgaadauth_list_principals(false)可查看到用户名与ObjectId的关联,是否能用ObjectId替代UserId连接?
  3. 希望避免将UserId存入环境变量/配置文件,优先从访问令牌自动获取所需信息。
解决方案

核心原理说明

Azure PostgreSQL的AAD认证要求UserId必须与数据库中预先创建的AAD主体用户名完全匹配:

  • 该用户名可以是AAD用户的UPN(本地开发场景)、托管标识的名称或客户端ID(部署场景)
  • 令牌中的oid是Azure AD层面的对象ID,PostgreSQL无法直接通过它映射到数据库用户,因此不能直接用oid作为UserId。

适配多场景的UserId提取方案

根据不同环境的令牌claim差异,从令牌中提取对应的值作为UserId,前提是数据库中创建的AAD主体用户名与提取值一致:

代码实现

// 获取访问令牌(兼容本地VS和Azure托管标识)
var credential = new DefaultAzureCredential();
var accessToken = credential.GetToken(
    new TokenRequestContext(new[] { "https://ossrdbms-aad.database.windows.net/.default" }),
    CancellationToken.None);

// 解析JWT令牌
var handler = new JwtSecurityTokenHandler();
var jsonToken = handler.ReadJwtToken(accessToken.Token);

// 适配不同场景提取UserId
string userId;
// 本地VS开发:用UPN(对应数据库中创建的AAD用户)
var upnClaim = jsonToken.Claims.FirstOrDefault(c => c.Type == "upn");
// 托管标识场景1:用主体名称(对应数据库中按名称创建的托管标识用户)
var nameClaim = jsonToken.Claims.FirstOrDefault(c => c.Type == "name");
// 托管标识场景2:用客户端ID(对应数据库中按Client ID创建的托管标识用户)
var clientIdClaim = jsonToken.Claims.FirstOrDefault(c => c.Type == "client_id");

if (upnClaim != null)
{
    userId = upnClaim.Value;
}
else if (nameClaim != null)
{
    userId = nameClaim.Value;
}
else if (clientIdClaim != null)
{
    userId = clientIdClaim.Value;
}
else
{
    throw new InvalidOperationException("无法从访问令牌中获取有效的用户ID");
}

// 构建连接字符串
var host = "<server-name>.postgres.database.azure.com";
var database = "<database-name>";
var connectionString = 
    $"Host={host};" +
    $"Database={database};" +
    $"User Id={userId};" +
    $"Password={accessToken.Token};" +
    $"SSL Mode=Require;" +
    $"Trust Server Certificate=true";

// 建立数据库连接
using var pgSqlConnection = new NpgsqlConnection(connectionString);
pgSqlConnection.Open();

数据库用户创建示例

根据你选择的UserId类型,在Azure PostgreSQL中创建对应的AAD主体用户:

  1. 本地AAD用户(UPN):
CREATE USER "your-email@domain.com" WITH LOGIN PASSWORD 'dummy' ROLE azure_ad_user;
  1. 托管标识(名称):
CREATE USER "your-managed-identity-name" WITH LOGIN PASSWORD 'dummy' ROLE azure_ad_user;
  1. 托管标识(客户端ID):
CREATE USER '12345678-1234-1234-1234-1234567890ab' WITH LOGIN PASSWORD 'dummy' ROLE azure_ad_user;

注:Password为占位符,AAD认证时不会使用,但PostgreSQL语法要求必须指定。

内容的提问来源于stack exchange,提问作者Stanton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 21:35:08