免责声明:像这样标题的问题很常见,但没有答案为我提供解决方案,所以无论如何我都需要问它(使用一组新参数)。
问题
在 web.config 中声明了一个 webservice 客户端端点,如下所示:
<behaviors>
<endpointBehaviors>
<behavior name="bankid">
<clientCredentials>
<clientCertificate findValue="FP Testcert 2"
storeLocation="LocalMachine"
storeName="Root"
x509FindType="FindBySubjectName"/>
<serviceCertificate>
<defaultCertificate findValue="Test BankID SSL Root CA v1 Test"
storeLocation="LocalMachine"
storeName="Root"
x509FindType="FindBySubjectName"/>
<authentication certificateValidationMode="None"
revocationMode="NoCheck"
trustedStoreLocation="LocalMachine"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
使用“管理计算机证书”应用程序安装证书(客户端和服务器证书)。它们分别存储在 .cer 文件(服务器证书)和 .pfx 文件(客户端证书)中。它们都存储在“受信任的根证书颁发机构”中。
成功
使用 Visual Studio 调试网络服务器 (IIS Express) 运行客户端是成功的。
失败
但是,当我尝试在 IIS 中运行它时,我收到错误消息
无法为具有权限“site.com”的 SSL/TLS 建立安全通道
问题解决方法
我试图创建一个 web api 函数,让我知道服务器是否找到了有问题的证书。确实如此。代码看起来像
[HttpGet]
[Route("Debug/certs")]
public CertsOutput certs()
{
var certStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
certStore.Open(OpenFlags.ReadOnly);
var config = System.Web.Configuration.WebConfigurationManager
.OpenWebConfiguration("~");
var group = ServiceModelSectionGroup.GetSectionGroup(config);
var endPointBehaviors = group.Behaviors.EndpointBehaviors;
var endpointBehavior = endPointBehaviors[0];
var ClientCredential = (ClientCredentialsElement) endpointBehavior[0];
var clientCert = ClientCredential.ClientCertificate;
var serverCert = ClientCredential.ServiceCertificate.DefaultCertificate;
var result = new CertsOutput
{
clientCert = new CertsOutput.Cert
{
FindValue = clientCert.FindValue,
StoreName = clientCert.StoreName.ToString(),
StoreLocation = clientCert.StoreLocation.ToString(),
FindType = clientCert.X509FindType.ToString()
},
serverCert = new CertsOutput.Cert
{
FindValue = serverCert.FindValue,
StoreName = serverCert.StoreName.ToString(),
StoreLocation = serverCert.StoreLocation.ToString(),
FindType = serverCert.X509FindType.ToString()
}
};
return result;
}
public class CertsOutput
{
public Cert clientCert { get; set; }
public Cert serverCert { get; set; }
public class Cert
{
public string FindValue { get; set; }
public string StoreName { get; set; }
public string StoreLocation { get; set; }
public string FindType { get; set; }
public string Expiration => Certificate?.GetExpirationDateString()
?? "Cant find cert";
X509Certificate _certificate = null;
private X509Certificate Certificate
{
get
{
if (_certificate != null)
return _certificate;
StoreName storeNameEnum;
switch(StoreName)
{
case "My":
storeNameEnum = System_StoreName.My;
break;
case "Root":
storeNameEnum = System_StoreName.Root;
break;
default:
throw new Exception("Unknown store name: " + StoreName);
}
StoreLocation storeLocationEnum;
switch(StoreLocation)
{
case "LocalMachine":
storeLocationEnum = System_StoreLocation.LocalMachine;
break;
case "CurrentUser":
storeLocationEnum = System_StoreLocation.CurrentUser;
break;
default:
throw new Exception("Unknown store location: " + StoreLocation);
}
var certStore = new X509Store(storeNameEnum, storeLocationEnum);
certStore.Open(OpenFlags.ReadOnly);
var certCollection = certStore.Certificates.Find
(X509FindType.FindBySubjectName, FindValue, validOnly:false);
certStore.Close();
var result = certCollection[0];
_certificate = result;
return result;
}
}
}
}
即使我在 IIS 上运行它,我也会得到这样的输出(在 chrome 中使用 console.log):
因此证书对 IIS 是清晰可见的,尽管它们存储在“受信任的根证书颁发机构”中。可以检索过期日期的唯一方法是使用商店。