certificate - 如何将证书附加到 ODATA 服务的 C# 客户端?

标签 certificate odata client-certificates

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

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

我们可以使用 HTTPClient 添加证书, 但我们想避免使用 HTTPClient与我们的 ODATA 服务对话并更喜欢使用 AddWebReference 方法。

最佳答案

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

This article实际上非常详细地解释了需要什么。

您需要添加 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具有您需要的证书的属性(property):

// 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是类型而不是 HttpWebRequestMessage导致 InvalidCastExceptions .这实际上是我最终提出这个问题的原因。似乎只有批处理操作才会出错。 InternalODataRequestMessage有一个 ODataBatchOperationRequestMessage 类型的私有(private)成员 requestMessage .它似乎没有我可以添加客户端证书的任何属性。

我已发布 another question关于该特定问题,如果我在此处提供的实现成为问题,将更改此答案。

关于certificate - 如何将证书附加到 ODATA 服务的 C# 客户端?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4351418/

相关文章:

ssl - 客户端证书如何工作?

c# - 如何让动态edm模型支持odata查询

xcode - Xcode 4 中未显示用于代码签名的自签名证书

wcf - "FindBySubjectName"找不到 X.509 证书

c# - 证书签名在服务器上产生不同的签名

wcf - 可以使用 WCF 数据服务返回文件吗?

rest - 使用 oData 访问 Cosmos DB 表端点

php - 使用 PHP 对文档进行数字签名

java - (Java) 没有发送必需的 SSL 证书(在 curl 调用中使用时工作正常)

ios - 通过 OSX 将证书安装到 iOS 设备