Как прикрепить сертификат к клиенту C # для службы ODATA? - PullRequest
3 голосов
/ 04 декабря 2010

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

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

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

1 Ответ

0 голосов
/ 20 января 2014

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...