我试图使用Azure Key Vault来存储实体框架的web api连接字符串。理想情况下,我希望避免将key vault nuget包与我的数据访问代码耦合。我的dbContext类有两个构造函数:
public MyDbContext() : base("DefaultConnection")
{ . . . }
public MyDbContext(string connectionString) : base(connectionString)
{ . . . }
我的代码使用了从web配置中获取连接字符串的无参数构造函数。我在某些地方实例化了一个新的MyDbContext对象,这禁止了使用注入的解决方案。
我采用的路线是在我的dbcontext上设置一个带有连接字符串定位器的静态属性:
public interface IConnectionStringLocator
{ string Get(); }
public class DefaultConnectionStringLocator : IConnectionStringLocator
{
public string Get()
{
return "DefaultConnection";
}
}
public static IConnectionStringLocator ConnectionStringLocator { get; set; } =
new DefaultConnectionStringLocator();
我的web api项目有用于检索密钥库机密的nuget包。因此,在我的global.asax文件中,我有以下内容:
protected void Application_Start()
{
MyDbContext.ConnectionStringLocator = new ConnectionStringLocator("DefaultConnection");
}
public class ConnectionStringLocator : IConnectionStringLocator
{
private readonly string _connectionStringName;
public ConnectionStringLocator(string connectionStringName)
{
this._connectionStringName = connectionStringName;
}
public string Get()
{
var keyVaultName = WebConfigurationManager.AppSettings.Get("KeyVaultName");
if (keyVaultName == "develop")
return _connectionStringName;
else
{
AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient =
new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
var defaultConnectionSecret =
keyVaultClient.GetSecretAsync($"https://{keyVaultName}.vault.azure.net/secrets/{this._connectionStringName}");
return defaultConnectionSecret.Result.Value;
}
}
}
我发表了这篇文章,它很有效,但它“感觉”不对。
另一个选择是遵循本文https://blog.falafel.com/keeping-secrets-with-azure-key-vault/但这需要我将KeyVault API包与我的数据访问连接起来。
我在寻找反馈和方向。我应该补充的是,我想使用key vault的原因是,它允许我拥有azure管理员,他们可以在线查看应用程序设置,而无需通过连接字符串访问sql数据库。
具有新MSI实现的KeyVault资源:https://github.com/azure-samples/app-service-msi-keyvault-dotnet/
以下是我如何解决这个问题的,以防其他人绊倒。
创建了一个ConfigurationManager类,该类首先尝试从密钥库中获取值,但失败后使用WebConfigurationManager读取应用程序设置。
public static class ConfigurationManager
{
public static string KeyVaultName => WebConfigurationManager.AppSettings.Get("KeyVaultName");
private static readonly Dictionary<string, string> ConfigurationCache = new Dictionary<string, string>();
private static SecretBundle GetSecret(string secretName, string vaultName = null)
{
AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient =
new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
var secretUri = $"https://{vaultName ?? KeyVaultName}.vault.azure.net/secrets/{secretName}";
var secret = keyVaultClient.GetSecretAsync(secretUri);
return secret.Result;
}
public static string GetAppSettingValue(string secretName, string vaultName = null)
{
vaultName = vaultName ?? KeyVaultName;
string key = $"{vaultName}:{secretName}";
string value;
if (ConfigurationCache.TryGetValue(key, out value))
return value;
if (string.IsNullOrEmpty(vaultName) || vaultName == "develop")
{
value = WebConfigurationManager.AppSettings.Get(secretName);
ConfigurationCache.Add(key, value);
return value;
}
var secret = GetSecret(secretName);
value = secret.Value;
ConfigurationCache.Add(key, value);
return value;
}
public static void SetAppSettingValue(string secretName, string value, string vaultName = null)
{
vaultName = vaultName ?? KeyVaultName;
string key = $"{vaultName}:{secretName}";
if (ConfigurationCache.ContainsKey(key))
ConfigurationCache[key] = value;
else
{
WebConfigurationManager.AppSettings[key] = value;
ConfigurationCache.Add(key, value);
}
}
public static string GetConnectionStringValue(string secretName, string vaultName = null)
{
vaultName = vaultName ?? KeyVaultName;
string key = $"{vaultName}:{secretName}";
string value;
if (ConfigurationCache.TryGetValue(key, out value))
return value;
if (string.IsNullOrEmpty(vaultName) || vaultName == "develop")
{
value = WebConfigurationManager.ConnectionStrings[secretName].ConnectionString;
ConfigurationCache.Add(key, value);
return value;
}
var secret = GetSecret(secretName);
value = secret.Value;
ConfigurationCache.Add(key, value);
return value;
}
}
然后,在我的dbcontext类中,我调用ConfigurationManager.GetConnectionStringValue(“DefaultConnection”)。
public MyDbContext()
: base(ConfigurationManager.GetConnectionStringValue("DefaultConnection"))
{...}
我的web api项目有用于检索密钥库机密的nuget包。因此,在我的global.asax文件中,我有以下内容: 我发表了这篇文章,它起作用了,但它“感觉”不对。 另一个选择是遵循本文https://blog.falafel.com/keeping-secrets-with-azure-key-vault/的内容,但这需要我将KeyVault API包与数据访问耦合起来。
我使用HTTPTrigger创建了一个简单的Azure函数,该函数通过Azure中的门户返回密钥集的秘密值。该值存储为 https://medium.com/statuscode/getting-key-vault-secrets-in-azure-functions-37620FD20A0B
我做错了什么试图在我的功能v2应用程序设置以下设置。 在函数中读取这些内容,我得到的是完整字符串,而不是我所期望的密钥库中的连接字符串。 我需要多走几步吗?
我在大多数文章中读到,需要在Azure中部署应用程序,这样应用程序才能以编程方式访问存储在Azure密钥库中的秘密。 有没有一种方法可以不在azure中部署应用程序,并且仍然能够通过使用客户端id和客户端机密或证书来访问azure密钥库以获取机密?
问题内容: 我试图从存储过程中获取简单的输出 和我的MVC 但是当我编译时,在以下部分出现错误: 方法’sp_getrandomnumber’的重载没有接受1个参数 名称“ randoms”在当前上下文中不存在 提前非常感谢希什 问题答案: 您的问题是您的SPROC输出是一个int。 请参见Scott Gu的文章中的以下引用。 “ LINQ to SQL将SPROC中的“ out”参数映射为参考参