开发者

How to attach a certificate to a C# client for an ODATA service?

开发者 https://www.devze.com 2023-01-28 15:44 出处:网络
We have an ODATA service which is being secured using certificates. We are using AddWebReference to get the proxy in our C# code.

We have an ODATA service which is being secured using certificates. We are using AddWebReference to get the proxy in our C# code.

Is there a way to attach the certificate that is in our certificate store to this generated proxy class?

We can add the certificate using HTTPClient, but we would like to avoid using HTTPClient t开发者_开发知识库o talk to our ODATA service and prefer to use the AddWebReference method.


I guess this is probably 3 years too late for you, but hopefully someone else will be helped.

This article actually explains in great detail what is required.

You need to add a ClientCertificate property to the container generated by adding a web reference and use it. You can do this by creating a partial class that adds the behaviour:

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);
        }
    }
}

On the instantiated container you can now set the ClientCertificate property with the certificate you need:

// 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+ (not completely working)

Now if you're using WCF Dataservice 5+, then the SendingRequest event has been deprecated as indicated with the attribute [Obsolete("SendingRequest2 has been deprecated in favor of SendingRequest2.")] (not a typo on my side ;) ). I think you can still use it though, however, if you want to use SendingRequest2, your partial should look something like the following:

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);
        }
    }
}

This worked for me for non-batch requests (found by trial and error as I couldn't find a lot of documentation about the differences between the SendingRequest and SendingRequest2).

However I seem to be experiencing some trouble now with args.RequestMessage being of type instead of HttpWebRequestMessage resulting in InvalidCastExceptions. Which is actually the reason I ended up on this question. It seems that it only goes wrong with Batch operations. The InternalODataRequestMessage has a private member requestMessage of type ODataBatchOperationRequestMessage. It doesn't seem to have any property to which I can add client certificates.

I have posted another question about that specific issue and will change this answer if the implementation I provided here turns out to be the problem.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号