You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

.Net Framework 4/4.5应用中不依赖ClientID与ClientSecret获取访问令牌,调用Azure Key Vault REST API获取密钥的实现方案

.Net Framework 4/4.5应用中不依赖ClientID与ClientSecret获取访问令牌,调用Azure Key Vault REST API获取密钥的实现方案

我完全懂你的顾虑——用客户端密钥去换Key Vault的访问令牌,本质上还是在代码里硬编码了另一个敏感凭据,根本没解决“密钥蔓延”的问题。托管身份确实是更安全的零凭据方案,而且针对你的.Net Framework 4/4.5环境,不管是部署在Azure App Service还是VM上,都有可行的实现方式,不用再存任何明文凭据。

下面分两种部署环境给你详细讲实现步骤和代码:

一、前置准备(两种环境通用)

首先得给你的Azure资源(App Service/VM)启用托管身份,并给它分配Key Vault的访问权限:

  • 启用系统分配托管身份:在Azure Portal里找到你的App Service/VM,进入「身份」选项卡,切换到「系统分配」标签,把状态设为「开启」,点击保存。系统会自动给这个资源创建一个AD身份。
  • 配置Key Vault访问策略:打开你的Key Vault,进入「访问策略」,点击「添加访问策略」:
    • 权限选择「机密权限」里的「获取」(根据你的需求添加其他权限);
    • 主体选择刚才创建的托管身份(名称和你的App Service/VM名称一致);
    • 保存策略。

二、代码实现:通过托管身份获取令牌并调用Key Vault REST API

因为.Net Framework 4/4.5不支持最新的Azure.Identity SDK,我们直接通过调用Azure Instance Metadata Service(IMDS)的端点来获取托管身份令牌,全程不需要硬编码任何凭据。

1. 获取托管身份访问令牌的方法

这个方法适用于App Service和VM两种环境:

using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json; // 需要安装Newtonsoft.Json NuGet包

public async Task<string> GetManagedIdentityAccessToken()
{
    using (var client = new HttpClient())
    {
        // 必须添加Metadata请求头,否则IMDS端点会拒绝请求
        client.DefaultRequestHeaders.Add("Metadata", "true");
        
        // 请求令牌的端点,resource指定为Key Vault的资源标识符
        var tokenRequestUri = new Uri("http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://vault.azure.net");
        
        var response = await client.GetAsync(tokenRequestUri);
        response.EnsureSuccessStatusCode(); // 如果请求失败,直接抛出异常
        
        var responseJson = await response.Content.ReadAsStringAsync();
        var tokenData = JsonConvert.DeserializeAnonymousType(responseJson, new { access_token = "" });
        
        return tokenData.access_token;
    }
}

2. 调用Key Vault REST API获取机密

拿到令牌后,就可以调用Key Vault的REST API获取目标机密了:

public async Task<string> GetSecretFromKeyVault(string keyVaultUrl, string secretName)
{
    var accessToken = await GetManagedIdentityAccessToken();
    
    using (var kvClient = new HttpClient())
    {
        // 添加Bearer令牌到请求头
        kvClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");
        
        // Key Vault REST API的请求地址,注意指定api-version(推荐用最新的稳定版)
        var secretRequestUri = new Uri($"{keyVaultUrl}/secrets/{secretName}?api-version=7.4");
        
        var secretResponse = await kvClient.GetAsync(secretRequestUri);
        secretResponse.EnsureSuccessStatusCode();
        
        var secretJson = await secretResponse.Content.ReadAsStringAsync();
        var secretData = JsonConvert.DeserializeAnonymousType(secretJson, new { value = "" });
        
        return secretData.value;
    }
}

3. 调用示例

现在你可以直接用这个方法,不需要任何硬编码的凭据:

string keyVaultUrl = "https://your-vault-name.vault.azure.net";
string secretName = "Test";

string secretValue = await GetSecretFromKeyVault(keyVaultUrl, secretName);
// 后续使用secretValue即可

三、额外说明

  • 如果用的是用户分配托管身份,只需要在令牌请求Uri里加上&client_id={你的用户分配身份的ClientID}参数即可,其他代码不变。
  • 确保你的应用可以访问IMDS端点(http://169.254.169.254),这个在Azure环境里是默认允许的,不需要额外配置网络规则。
  • 相比之前的方案,这个实现完全消除了代码中的敏感凭据,所有身份验证都由Azure后台自动处理,安全性大幅提升。

备注:内容来源于stack exchange,提问作者AskMe

火山引擎 最新活动