【发布时间】:2018-03-04 16:53:42
【问题描述】:
我需要将客户端证书(作为实例,而不是来自 Windows 证书存储)设置到我的 wcf 通道,但我总是得到异常:
System.InvalidOperationException: "对象是只读的。"
这很奇怪,因为这些属性有一个 setter 但如果我分配了 X509Certificate2 就会崩溃。
堆栈跟踪
System.InvalidOperationException
HResult=0x80131509
Nachricht = Object is read-only.
Quelle = System.Private.ServiceModel
Stapelüberwachung:
at System.ServiceModel.Security.X509CertificateRecipientClientCredential.ThrowIfImmutable()
at System.ServiceModel.Security.X509CertificateRecipientClientCredential.set_DefaultCertificate(X509Certificate2 value)
代码
var binding = new BasicHttpsBinding();
var endpoint = new EndpointAddress(new Uri("https://myservice.com"));
var channelFactory = new ChannelFactory<MyService>(binding, endpoint);
var serviceClient = channelFactory.CreateChannel();
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
var token = GetToken(); // Just an method that reads a pfx from disk
channelFactory.Credentials.
ServiceCertificate.DefaultCertificate = token.Certificate; // throws exception
channelFactory.Credentials.
ClientCertificate.Certificate = token.Certificate; // throws exception too
更新 1
方法SetCertificate 抛出同样的System.InvalidOperationException: "Object is read-only." 异常。
using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
store.Open(OpenFlags.ReadWrite);
var x509Certificate2Collection = store.Certificates.Find(X509FindType.FindByThumbprint, token.Certificate.Thumbprint, false);
if(x509Certificate2Collection.Count == 0)
store.Add(token.Certificate);
}
channelFactory.Credentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My,X509FindType.FindByThumbprint, token.Certificate.Thumbprint);
更新 2
X509CertificateRecipientClientCredential.cs 的实现很有趣。
public X509Certificate2 DefaultCertificate
{
get
{
return _defaultCertificate;
}
set
{
ThrowIfImmutable();
_defaultCertificate = value;
}
}
internal void MakeReadOnly()
{
_isReadOnly = true;
this.Authentication.MakeReadOnly();
if (_sslCertificateAuthentication != null)
{
_sslCertificateAuthentication.MakeReadOnly();
}
}
private void ThrowIfImmutable()
{
if (_isReadOnly)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.ObjectIsReadOnly)));
}
}
某事打电话给internal void MakeReadOnly(),让我的生活变得更加艰难。
【问题讨论】:
-
GetToken()是什么?请阅读How to Ask 和edit 您的问题以包含minimal reproducible example -
@CamiloTerevinto 我将问题编辑得更清楚。
-
如果您将
var替换为GetToken() 行中的实际类型,这将有所帮助。 -
我记得有一个 ClientCertificate.SetCertificate(...) 方法,你在这里看到了吗?列出您尝试过的所有死胡同。
-
你不知道是谁打电话的吗?因为原因也将指向解决它的方法。有很多方法可以设置这些证书和凭证类型。
标签: c# wcf asp.net-core client-certificates