Как подключить сертификат к клиенту С# для службы ODATA?

У нас есть служба ODATA, которая защищена с использованием сертификатов. Мы используем AddWebReference для получения прокси в нашем коде на С#.

Есть ли способ привязать сертификат, который находится в нашем хранилище сертификатов к этому сгенерированному прокси-классу?

Мы можем добавить сертификат, используя HTTPClient, но мы бы хотели избежать использования HTTPClient, чтобы поговорить с нашей службой ODATA и предпочитаем использовать метод AddWebReference.

1 ответ

Я думаю, это, вероятно, уже на 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 имеет частный член requestMessage типа ODataBatchOperationRequestMessage. У него нет никакого свойства, к которому я могу добавить клиентские сертификаты.

Я отправил еще один вопрос об этой конкретной проблеме и изменит этот ответ, если проблема, которую я предоставил здесь, оказывается проблемой.

licensed under cc by-sa 3.0 with attribution.