C#:如何使用运行时安装的证书调用需要客户端身份验证的SOAP服务

pet*_*uim 8 c# iis wcf soap client-certificates

我有一个部署到IIS的应用程序,需要调用SOAP服务。它使用.NET Framework中的WCF。该SOAP服务要求使用在运行时提供的客户端证书对请求进行身份验证。应用程序的管理员用户可以在后台更新使用的证书。目的是实现自治,并且证书生命周期管理独立于IIS或基础系统,因此不能选择使用计算机证书存储。这是初始代码:

var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
var client = new ServiceReference1.myClient(binding, new EndpointAddress(serviceUrl));
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
var certificate = new X509Certificate2(certificateBinary, certificatePassword);
client.ClientCredentials.ClientCertificate.Certificate = certificate;

//use the client
var result = client.myMethod(new ServiceReference1.MethodRequest());
Run Code Online (Sandbox Code Playgroud)

certificateBinary是加载包含完整证书链(客户端证书,中间CA和根CA)以及certificatePassword用于创建该文件的密码的PFX文件的结果。但是该请求被服务器拒绝。通过查看Wireshark,似乎只发送了客户端证书。这与我们将PFX安装在可以正常工作的机器存储上时的情况不同。

因此,我尝试的下一步是在运行时安装证书。首先加载它们:

X509Certificate2Collection collection = new X509Certificate2Collection();
try {
    collection.Import(ssCertificateFile, ssPassword, X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.PersistKeySet);
}
Run Code Online (Sandbox Code Playgroud)

然后确定它们是哪种证书,最后将它们安装在当前用户存储中:

private static void InstallCertificates(X509Certificate2Collection clientCerts, X509Certificate2Collection intermediateCAs, X509Certificate2Collection RootCAs) {
    using (X509Store personalStore = new X509Store(StoreName.My, StoreLocation.CurrentUser)) {
        personalStore.Open(OpenFlags.ReadWrite);
        personalStore.AddRange(clientCerts);
    }

    using (X509Store intermediateStore = new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser)) {
        intermediateStore.Open(OpenFlags.ReadWrite);
        intermediateStore.AddRange(intermediateCAs);
    }

    using (X509Store trustedCAsStore = new X509Store(StoreName.Root, StoreLocation.CurrentUser)) {
        trustedCAsStore.Open(OpenFlags.ReadWrite);
        trustedCAsStore.AddRange(rootCAs);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用以下命令在受信任的根证书颁发机构(StoreName.Root)中安装根CA时,此操作将失败:

System.Security.Cryptography.CryptographicException: The request is not supported.
   at System.Security.Cryptography.X509Certificates.X509Store.Add(X509Certificate2 certificate)
   at System.Security.Cryptography.X509Certificates.X509Store.AddRange(X509Certificate2Collection certificates)
   at OutSystems.NssCertificationExtremeXP.CssCertificationExtremeXP.InstallCertificates(CertificatesClassifier certificates)
Run Code Online (Sandbox Code Playgroud)

因此仅安装客户端证书和中间CA,显然在运行时这还不够。

但是,如果我使用完全相同的代码并在单独的C#项目中运行它,则在安装根CA时会出现一个确认对话框 ,如果单击“确定”,则证书已安装。

这里这里,每次我们想要在用户受信任的根证书颁发机构中安装某些内容时,都会出现该提示,并且在非GUI使用的上下文中可能不支持该提示。

问题是,即使我没有在存储中安装根CA,也可以在运行此独立应用程序时成功调用SOAP服务,只有在IIS下运行时,此操作才会失败。

有谁知道为什么会这样以及如何解决呢?