3

我们有一个使用证书保护的 ODATA 服务。我们正在使用 AddWebReference 在我们的 C# 代码中获取代理。

有没有办法将我们证书存储中的证书附加到这个生成的代理类?

我们可以使用 来添加证书HTTPClient,但我们希望避免使用HTTPClient来与我们的 ODATA 服务通信,而是更喜欢使用 AddWebReference 方法。

4

1 回答 1

0

我想这对您来说可能为时已晚 3 年,但希望其他人会得到帮助。

这篇文章实际上非常详细地解释了需要什么。

您需要将ClientCertificate属性添加到通过添加 Web 引用生成的容器中并使用它。您可以通过创建一个添加行为的部分类来做到这一点:

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

这对我来说适用于非批量请求(通过反复试验发现,因为我找不到很多关于 和 之间差异的文档SendingRequestSendingRequest2

但是,我现在似乎遇到了一些麻烦,因为我args.RequestMessage是 type 而不是HttpWebRequestMessage导致InvalidCastExceptions. 这实际上是我最终提出这个问题的原因。似乎只有批处理操作才会出错。有InternalODataRequestMessage一个私有成员 requestMessage 类型ODataBatchOperationRequestMessage。它似乎没有我可以添加客户端证书的任何属性。

我已经发布了关于该特定问题的另一个问题,如果我在此处提供的实施结果证明是问题,我将更改此答案。

于 2014-01-20T14:29:00.913 回答