突发 'No valid key mapping found for securityToken' 错误
Sudden 'No valid key mapping found for securityToken' error
TL;DR
我们的网站突然出现以下错误,没有代码或 web.config
更改。 Azure 会改变吗?
我有一个网站 运行 在 Azure 上几个月没有出现任何问题。然后前几天,我们现在有这个错误:
WIF10201: No valid key mapping found for securityToken: 'System.IdentityModel.Tokens.X509SecurityToken' and issuer: 'https://sts.windows.net/<guid>/'.
我们未对 web.config
或 Tenants
和 IssuingAuthorityKeys
中的值进行任何更改。
搜索 SO 和网络给出了很多基于代码的答案,但我们没有更改任何代码。
web.config
是这样的:
<system.identityModel>
<identityConfiguration>
<issuerNameRegistry type="DatabaseIssuerNameRegistry, Site.Web" />
<audienceUris>
<add value="https://localhost:44301" />
<add value="https://<other urls...>" />
</audienceUris>
<securityTokenHandlers>
<add type="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<remove type="System.IdentityModel.Tokens.SessionSecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</securityTokenHandlers>
<certificateValidation certificateValidationMode="None" />
</identityConfiguration>
</system.identityModel>
issuerNameRegistry
class如下:
public class DatabaseIssuerNameRegistry : ValidatingIssuerNameRegistry
{
public static bool ContainsTenant(string tenantId)
{
using (DBEntities context = new DBEntities())
{
return context.Tenants
.Where(tenant => tenant.Id == tenantId)
.Any();
}
}
public static bool ContainsKey(string thumbprint)
{
using (DBEntities context = new DBEntities())
{
return context.IssuingAuthorityKeys
.Where(key => key.Id == thumbprint)
.Any();
}
}
public static void RefreshKeys(string metadataLocation)
{
IssuingAuthority issuingAuthority = ValidatingIssuerNameRegistry.GetIssuingAuthority(metadataLocation);
bool newKeys = false;
bool refreshTenant = false;
foreach (string thumbprint in issuingAuthority.Thumbprints)
{
if (!ContainsKey(thumbprint))
{
newKeys = true;
refreshTenant = true;
break;
}
}
foreach (string issuer in issuingAuthority.Issuers)
{
if (!ContainsTenant(GetIssuerId(issuer)))
{
refreshTenant = true;
break;
}
}
if (newKeys || refreshTenant)
{
using (DBEntities context = new DBEntities())
{
if (newKeys)
{
context.IssuingAuthorityKeys.RemoveRange(context.IssuingAuthorityKeys);
foreach (string thumbprint in issuingAuthority.Thumbprints)
{
context.IssuingAuthorityKeys.Add(new IssuingAuthorityKey { Id = thumbprint });
}
}
if (refreshTenant)
{
foreach (string issuer in issuingAuthority.Issuers)
{
string issuerId = GetIssuerId(issuer);
if (!ContainsTenant(issuerId))
{
context.Tenants.Add(new Tenant { Id = issuerId });
}
}
}
context.SaveChanges();
}
}
}
private static string GetIssuerId(string issuer)
{
return issuer.TrimEnd('/').Split('/').Last();
}
protected override bool IsThumbprintValid(string thumbprint, string issuer)
{
return ContainsTenant(GetIssuerId(issuer))
&& ContainsKey(thumbprint);
}
}
从 this Technet
文章来看,微软似乎已经更新了他们处理 Tenant
键的方式。
我必须将以下代码添加到我的 Global.asax.cs
文件中:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
// ....
string configPath = AppDomain.CurrentDomain.BaseDirectory + "\" + "Web.config";
string metadataAddress =
ConfigurationManager.AppSettings["ida:FederationMetadataLocation"];
ValidatingIssuerNameRegistry.WriteToConfig(metadataAddress, configPath);
}
查看我在类似 post 上的回答。它仅适用于在 VS2013 或更高版本中创建的解决方案。
这是它的副本:
对于在 VS2013 及更高版本中创建的解决方案,解决方案应包含自动滚动密钥的逻辑。无需将值放入 web.config 文件中。
将您的解决方案从本地迁移到另一个环境时,您可能 运行 遇到此问题。在这种情况下,您可能会尝试将您的解决方案指向 Azure Active Directory 中的新应用程序。检查以下内容:
- 确保 web.config 中的所有 url 都指向正确的 url 而不是您在本地设置时自动生成的
- 从 IssuingAuthorityKeys 中删除所有条目 table。当您重新构建解决方案并 运行 时,这些键将自动填充。在服务器上,您可能需要手动替换 dll 才能刷新
- 最后也是最重要的,从租户 table 中删除所有行。在新环境的第一个 运行 中,拥有 Active Directory 的管理员必须注册并授权应用程序。
如果执行这些步骤后两个 table 中的值仍未自动填充,请查看此 article 以了解有关如何手动获取值的步骤。
TL;DR
我们的网站突然出现以下错误,没有代码或 web.config
更改。 Azure 会改变吗?
我有一个网站 运行 在 Azure 上几个月没有出现任何问题。然后前几天,我们现在有这个错误:
WIF10201: No valid key mapping found for securityToken: 'System.IdentityModel.Tokens.X509SecurityToken' and issuer: 'https://sts.windows.net/<guid>/'.
我们未对 web.config
或 Tenants
和 IssuingAuthorityKeys
中的值进行任何更改。
搜索 SO 和网络给出了很多基于代码的答案,但我们没有更改任何代码。
web.config
是这样的:
<system.identityModel>
<identityConfiguration>
<issuerNameRegistry type="DatabaseIssuerNameRegistry, Site.Web" />
<audienceUris>
<add value="https://localhost:44301" />
<add value="https://<other urls...>" />
</audienceUris>
<securityTokenHandlers>
<add type="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<remove type="System.IdentityModel.Tokens.SessionSecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</securityTokenHandlers>
<certificateValidation certificateValidationMode="None" />
</identityConfiguration>
</system.identityModel>
issuerNameRegistry
class如下:
public class DatabaseIssuerNameRegistry : ValidatingIssuerNameRegistry
{
public static bool ContainsTenant(string tenantId)
{
using (DBEntities context = new DBEntities())
{
return context.Tenants
.Where(tenant => tenant.Id == tenantId)
.Any();
}
}
public static bool ContainsKey(string thumbprint)
{
using (DBEntities context = new DBEntities())
{
return context.IssuingAuthorityKeys
.Where(key => key.Id == thumbprint)
.Any();
}
}
public static void RefreshKeys(string metadataLocation)
{
IssuingAuthority issuingAuthority = ValidatingIssuerNameRegistry.GetIssuingAuthority(metadataLocation);
bool newKeys = false;
bool refreshTenant = false;
foreach (string thumbprint in issuingAuthority.Thumbprints)
{
if (!ContainsKey(thumbprint))
{
newKeys = true;
refreshTenant = true;
break;
}
}
foreach (string issuer in issuingAuthority.Issuers)
{
if (!ContainsTenant(GetIssuerId(issuer)))
{
refreshTenant = true;
break;
}
}
if (newKeys || refreshTenant)
{
using (DBEntities context = new DBEntities())
{
if (newKeys)
{
context.IssuingAuthorityKeys.RemoveRange(context.IssuingAuthorityKeys);
foreach (string thumbprint in issuingAuthority.Thumbprints)
{
context.IssuingAuthorityKeys.Add(new IssuingAuthorityKey { Id = thumbprint });
}
}
if (refreshTenant)
{
foreach (string issuer in issuingAuthority.Issuers)
{
string issuerId = GetIssuerId(issuer);
if (!ContainsTenant(issuerId))
{
context.Tenants.Add(new Tenant { Id = issuerId });
}
}
}
context.SaveChanges();
}
}
}
private static string GetIssuerId(string issuer)
{
return issuer.TrimEnd('/').Split('/').Last();
}
protected override bool IsThumbprintValid(string thumbprint, string issuer)
{
return ContainsTenant(GetIssuerId(issuer))
&& ContainsKey(thumbprint);
}
}
从 this Technet
文章来看,微软似乎已经更新了他们处理 Tenant
键的方式。
我必须将以下代码添加到我的 Global.asax.cs
文件中:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
// ....
string configPath = AppDomain.CurrentDomain.BaseDirectory + "\" + "Web.config";
string metadataAddress =
ConfigurationManager.AppSettings["ida:FederationMetadataLocation"];
ValidatingIssuerNameRegistry.WriteToConfig(metadataAddress, configPath);
}
查看我在类似 post 上的回答。它仅适用于在 VS2013 或更高版本中创建的解决方案。
这是它的副本:
对于在 VS2013 及更高版本中创建的解决方案,解决方案应包含自动滚动密钥的逻辑。无需将值放入 web.config 文件中。
将您的解决方案从本地迁移到另一个环境时,您可能 运行 遇到此问题。在这种情况下,您可能会尝试将您的解决方案指向 Azure Active Directory 中的新应用程序。检查以下内容:
- 确保 web.config 中的所有 url 都指向正确的 url 而不是您在本地设置时自动生成的
- 从 IssuingAuthorityKeys 中删除所有条目 table。当您重新构建解决方案并 运行 时,这些键将自动填充。在服务器上,您可能需要手动替换 dll 才能刷新
- 最后也是最重要的,从租户 table 中删除所有行。在新环境的第一个 运行 中,拥有 Active Directory 的管理员必须注册并授权应用程序。
如果执行这些步骤后两个 table 中的值仍未自动填充,请查看此 article 以了解有关如何手动获取值的步骤。