Полагаю, для вас это, вероятно, на 3 года позже, но, надеюсь, кому-то еще помогут.
Эта статья на самом деле очень подробно объясняет, что требуется.
Вам необходимо добавить свойство ClientCertificate
в контейнер, созданный путем добавления веб-ссылки, и использовать его. Вы можете сделать это, создав частичный класс, который добавляет поведение:
public partial class YourContainer
{
private X509Certificate clientCertificate = null;
public X509Certificate ClientCertificate
{
get
{
return clientCertificate;
}
set
{
if (value == null)
{
// if the event has been hooked up before, we should remove it
if (clientCertificate != null)
this.SendingRequest -= this.OnSendingRequest_AddCertificate;
}
else
{
// hook up the event if its being set to something non-null
if (clientCertificate == null)
this.SendingRequest += this.OnSendingRequest_AddCertificate;
}
clientCertificate = value;
}
}
private void OnSendingRequest_AddCertificate(object sender, SendingRequestEventArgs args)
{
if (null != ClientCertificate)
{
((HttpWebRequest)args.Request).ClientCertificates.Add(ClientCertificate);
}
}
}
В созданном контейнере теперь вы можете установить свойство ClientCertificate
с нужным вам сертификатом:
// Get the store where your certificate is in.
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
// Select your certificate from the store (any way you like).
X509Certificate2Collection certColl = store.Certificates.Find(X509FindType.FindByThumbprint, yourThumbprint, false);
// Set the certificate property on the container.
container.ClientCertificate = certColl[0];
store.Close();
WCF DataServices 5+ (не полностью работает)
Теперь, если вы используете WCF Dataservice 5+, событие SendingRequest устарело, как указано атрибутом [Obsolete("SendingRequest2 has been deprecated in favor of SendingRequest2.")]
(не опечатка на моей стороне;)). Я думаю, что вы все еще можете использовать его, однако, если вы хотите использовать SendingRequest2, ваше частичное должно выглядеть примерно так:
public partial class YourContainer
{
private X509Certificate clientCertificate = null;
public X509Certificate ClientCertificate
{
get
{
return clientCertificate;
}
set
{
if (value == null)
{
// if the event has been hooked up before, we should remove it
if (clientCertificate != null)
this.SendingRequest2 -= this.OnSendingRequest_AddCertificate;
}
else
{
// hook up the event if its being set to something non-null
if (clientCertificate == null)
this.SendingRequest2 += this.OnSendingRequest_AddCertificate;
}
clientCertificate = value;
}
}
private void OnSendingRequest_AddCertificate(object sender, SendingRequest2EventArgs args)
{
if (null != ClientCertificate)
{
((HttpWebRequestMessage)args.RequestMessage).HttpWebRequest.ClientCertificates.Add(ClientCertificate);
}
}
}
Это сработало для меня для не пакетных запросов (найдено методом проб и ошибок, так как я не смог найти много документации о различиях между SendingRequest
и SendingRequest2
).
Однако, похоже, сейчас я испытываю некоторые проблемы с args.RequestMessage
, имеющим тип вместо HttpWebRequestMessage
, что приводит к InvalidCastExceptions
. Что на самом деле является причиной, по которой я остановился на этом вопросе. Кажется, что это только идет не так с пакетными операциями. InternalODataRequestMessage
имеет запрос закрытого члена типа ODataBatchOperationRequestMessage
. Кажется, у него нет свойства, к которому я могу добавить клиентские сертификаты.
Я отправил другой вопрос об этой конкретной проблеме и изменит этот ответ, если приведенная здесь реализация окажется проблемой.