我正在开发一个基于Sustainsys.SAML2.HttpModule的ASP.NET SAML2服务提供商客户端。总的来说,Sustainsys似乎是一个成熟的库,我有一个使用SAML2身份验证的基本网站,并且运行得很快。然而,我遇到了一个阻碍我的问题。我们需要在代码中提供网站的配置,而不是在web.config中。这是完全可能的,除了SP<serviceCertificates>
集合。在这里,我们至少需要一个具有私钥的证书来对SP的断言进行签名。在CertificateElement
类中,有两个加载证书的选项:
- 从文件加载。这不起作用,因为SustainSys代码不可能指定文件的密码。包含私钥的证书文件必须具有密码
- 从证书存储加载。一般来说,只有当网站以LocalSystem运行时,这才会起作用。以常规用户身份运行的IIS应用程序池无法访问私钥,即使在CurrentUser/My存储中也无法访问,除非设置了应用程序池的"加载用户配置文件"设置。在托管环境中,您通常无法控制这一点
解决该问题最简单的方法是使用第三个选项,即CertificateElement
从X509Certificate2
对象加载其证书。
我的问题是:还有其他解决方案吗?我是不是忽略了什么?我更喜欢而不是编辑库代码
[编辑]使用@anders-abel的答案,我的复杂库更改根本不需要(我很高兴!(。我删除了那个代码大纲。
只剩下两样东西:
- 在应用程序启动之前,我注册了SustainSys HttpModule和我自己的一个HttpModule。为了初始化SustainSys,我编写了一个临时application.config文件并再次将其删除。现在,ServiceCertificates节点不再添加到该配置中
string configFilePath = Path.Combine(Path.GetTempPath(), configFileName);
StringBuilder sb = GetTextResource("sustainsys.config");
if (sb != null)
{
sb.Replace("$entityId", entityId);
//sb.Replace("$serviceCertificate", SigningCertificate.ToBase64String());
sb.Replace("$identityProviders", GetIdentityProvidersList());
File.WriteAllText(configFilePath, sb.ToString());
SustainsysSaml2Section.Configuration
= ConfigurationManager.OpenMappedExeConfiguration(
new ExeConfigurationFileMap() { ExeConfigFilename = configFilePath },
ConfigurationUserLevel.None, true);
File.Delete(configFilePath);
return true;
}
- 要使用Anders Abel的解决方案,我必须等待SustainSys模块初始化。我在自己的HttpModule initn中添加了服务证书,它在SustainSys的Init之后调用。因为这样做不止一次,所以我只在
ServiceCertificates.Count == 0
的情况下添加certifrate
/// <summary>
/// Initializes the Decos.Saml2 HttpModule.
/// </summary>
/// <param name="context"></param>
public void Init(HttpApplication context)
{
_usingIntegratedPipeline = HttpRuntime.UsingIntegratedPipeline;
context.BeginRequest += OnBeginRequest;
if (Enabled)
{
if (Saml2AuthenticationModule.Options.SPOptions.ServiceCertificates.Count == 0)
{
Saml2AuthenticationModule.Options.SPOptions.ServiceCertificates
.Add(ConfigSustainSys.SigningCertificate);
}
Saml2AuthenticationModule.Options.Notifications.Unsafe
.TokenValidationParametersCreated
= (validationParameters, idp, idpResponseXml) =>
{
SetBestMatchingNameClaim(validationParameters, idpResponseXml);
};
Saml2AuthenticationModule.Options.Notifications
.AcsCommandResultCreated = (result, response) =>
{
// TODO
};
}
}
使用web.config
时,支持指定存储等,从存储加载的代码在库中。
当从代码进行配置时,其想法是通过自己的代码获得X509Certificate2
实例。这可能是从存储、文件、数据库或任何东西加载。
然后使用它,您可以在SpOptions:中注册它
spOptions.ServiceCertificates.Add(myX509Certificate2);
或者,如果你想定义允许的用法:
spOptions.ServiceCertificates.InsertItem(0, new ServiceCertificate
{
Certificate = myX509Certificate2,
Use = CertificateUse.Signing
}