我们在Azure上的两个网络应用程序上部署了一个网站:生产版和预生产版。
网站在特定时间使用以下代码创建一个容纳RSA密钥的容器:
// -----------------------------
// Part 1 : Initialize csp params
// -----------------------------
const int PROVIDER_RSA_FULL = 1;
const string CONTAINER_NAME = "OurKeyContainer";
CspParameters cspParams;
cspParams = new CspParameters(PROVIDER_RSA_FULL);
cspParams.KeyContainerName = CONTAINER_NAME;
cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";
// --------------------------------------------------
// Part 2 : A try to set folder access rights to "everyone"
// --------------------------------------------------
// http://whowish-programming.blogspot.fr/2010/10/systemsecuritycryptographycryptographic.html
// http://stackoverflow.com/questions/5013881/c-sharp-how-do-i-get-the-everybody-user
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
var rule = new CryptoKeyAccessRule(sid, CryptoKeyRights.FullControl, AccessControlType.Allow);
cspParams.CryptoKeySecurity = new CryptoKeySecurity();
cspParams.CryptoKeySecurity.SetAccessRule(rule);
return new RSACryptoServiceProvider(cspParams);
问题是此代码仅适用于其中一个网站,实际上是首次启动的网站。第二个抛出了CryptographicException"对象已经存在"。
在谷歌搜索之后,问题似乎是由执行无权访问密钥容器的网站的用户引起的,但不幸的是推荐的修复(在我们上面的代码的第2部分中实现)不起作用..
有任何想法或建议吗?
由于
Riana
答案 0 :(得分:2)
我认为问题在于您基本上是在尝试创建两次具有相同名称的Machine wide容器。我假设pre-prod
和prod
环境位于同一台计算机上,可能是您的App Service中的部署插槽?我至少可以使用此设置复制您的问题。还有一些其他的设置可能会产生相同的情况,我猜,但这是最有可能的。
您可以在此设置中更改三项内容,以产生不同的结果:
对于身份,我们可以使用Everyone
(您已尝试过)或Current
我们可以从WindowsIdentity获取
private IdentityReference GetWindowsIdentity()
{
return System.Security.Principal.WindowsIdentity.GetCurrent().User;
}
private IdentityReference GetEveryoneIdentity()
{
return new SecurityIdentifier(WellKnownSidType.WorldSid, null);
}
容器商店可以是machine wide
,也可以只是当前用户
// machine wide store
var cspParams = new CspParameters(PROVIDER_RSA_FULL)
{
...
Flags = CspProviderFlags.UseMachineKeyStore;
...
};
// default store
var cspParams = new CspParameters(PROVIDER_RSA_FULL)
{
...
Flags = CspProviderFlags.UseDefaultKeyContainer;
...
};
对于商店名称我们可以选择一些东西,在你的情况下你选择相同但我们可以设置一些独特的身份
KeyContainerName = "OurKeyContainer",
KeyContainerName = $"OurKeyContainer-{identity}",
不同的组合会产生不同的结果:
每个人身份,计算机范围内的商店,相同的容器名称在System.Security.Cryptography.CryptographicException: Object already exists.
每个人身份,机器广告商店,每个身份的容器确定
每个人的身份,用户商店,相同的容器名称在System.Security.Cryptography.CryptographicException: The system cannot find the file specified.
每个人身份,用户商店,每个身份的容器确定
当前标识,计算机范围内的商店,相同的容器名称其中一个广告位System.Security.Cryptography.CryptographicException: Object already exists.
当前身份,计算机广告商店,每个身份的容器确定
目前的身份,用户商店,相同的容器名称 System.Security.Cryptography.CryptographicException: The system cannot find the file specified.
当前身份,用户存储,每个身份的容器 System.Security.Cryptography.CryptographicException: The system cannot find the file specified.
因此,总而言之,更改容器名称以包含对环境唯一的内容将解决问题。它不一定是身份(但是你将在机器上运行的每个App Service获得一个身份,因此它是相当安全的),如果你将它设置为{{1},它可能是环境的名称在您的App Service中,确保它分别设置为ENVIRONMENT VARIABLE
和pre-prod
。