在开发基于声明的身份验证应用程序时,为了使该应用程序在部署到负载平衡服务器时能够正常工作,我按照http://msdn.microsoft.com/en-us/library/ff803371.aspx使用RsaTokenTransform处理程序替换默认的SecurityTokenHandler,使用自己提供的证书加密会话cookie:
X509Certificate2 serviceCertificate = new X509Certificate2(certificate, certificatePassword);
List<CookieTransform> sessionTransformers =
new List<CookieTransform>
(
new CookieTransform[]
{
new DeflateCookieTransform(),
new RsaEncryptionCookieTransform(serviceCertificate),
new RsaSignatureCookieTransform(serviceCertificate)
}
);
SessionSecurityTokenHandler sessionHandler = new SessionSecurityTokenHandler(sessionTransformers.AsReadOnly());
FederatedAuthentication.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace(sessionHandler);
为了使应用程序更加灵活和可移植,在运行时从数据库中提取证书并将其存储在X509Certificate2对象中。 这是一个服务器托管的应用程序,但一旦我切换到服务器群,每隔一段时间我得到错误: ID1014:签名无效。数据可能被 还有一些javascript, css和字体文件因为同样的问题而无法加载。 相关问题但未解决的问题: WIF- ID1014:签名无效。数据可能被 WIF: ID1014:签名无效。数据可能被
在互联网上搜索后,我没有找到明确的解释或解决方案;为了节省可能遇到和我一样问题的人的时间,下面是解释:
问题的原因是默认情况下,X509Certificate2对象只提供临时Privatekey Provider,它不会在服务器场的不同服务器之间持久存在。一旦请求从原始服务器转到另一个服务器,Privatekey Provider在该服务器上变为空(因为它不持久),因此抛出异常,因为签名验证需要证书的私钥。
要解决这个问题,只需要在创建X509Certificate2对象时使Privatekey Provider持久:
X509Certificate2 serviceCertificate = new X509Certificate2(certificate, certificatePassword, X509KeyStorageFlags.MachineKeySet|X509KeyStorageFlags.PersistKeySet);