如何在 Azure 应用服务中将 X509Certificate2 与 WCF 一起使用

Posted

技术标签:

【中文标题】如何在 Azure 应用服务中将 X509Certificate2 与 WCF 一起使用【英文标题】:How to use an X509Certificate2 with WCF in Azure App Service 【发布时间】:2017-01-14 08:03:07 【问题描述】:

我目前正在开发一个在 Azure App Service 中运行的应用程序,该应用程序使用 WCF 和 TransportWithMessageCredential 调用另一个服务,以实现消息凭据的安全性和基于证书的身份验证。我能够从 Azure Key Vault 检索证书,并将该证书用于我的 WCF ChannelFactory 的客户端,以便在我的本地开发框中提供服务。但是,一旦我在 Azure App Service vm 上运行应用程序,我的所有调用都会出现以下异常:

System.Security.Cryptography.CryptographicException: m_safeCertContext is an invalid handle.
   at System.Runtime.AsyncResult.End (System.ServiceModel.Internals, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.ServiceModel.Channels.ServiceChannel+SendAsyncResult.End (System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.ServiceModel.Channels.ServiceChannel.EndCall (System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.ServiceModel.Channels.ServiceChannelProxy+TaskCreator+<>c__DisplayClass7_0`1.<CreateGenericTask>b__0 (System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at MyAzureAppServiceApp.Util.ServiceModelClient.ChannelFactoryExtensions+<UsingResultAsync>d__3`2.MoveNext (MyAzureAppServiceApp.Util.ServiceModelClient, Version=1.2.906.10, Culture=neutral, PublicKeyToken=null)
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at MyAzureAppServiceApp.Data.WidgetRepository+<GetWidgetsByProjectAsync>d__5.MoveNext (MyAzureAppServiceApp.Data, Version=1.2.906.10, Culture=neutral, PublicKeyToken=null)
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at MyAzureAppServiceApp.Service.Controllers.WidgetController+<GetWidgetsByProjectNumberAsync>d__6.MoveNext (MyAzureAppServiceApp.Service, Version=1.2.906.10, Culture=neutral, PublicKeyToken=null)
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Threading.Tasks.TaskHelpersExtensions+<CastToObject>d__3`1.MoveNext (System.Web.Http, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Web.Http.Controllers.ApiControllerActionInvoker+<InvokeActionAsyncCore>d__0.MoveNext (System.Web.Http, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Web.Http.Controllers.ActionFilterResult+<ExecuteAsync>d__2.MoveNext (System.Web.Http, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Web.Http.Filters.AuthorizationFilterAttribute+<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext (System.Web.Http, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Web.Http.Filters.AuthorizationFilterAttribute+<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext (System.Web.Http, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Web.Http.Controllers.ExceptionFilterResult+<ExecuteAsync>d__0.MoveNext (System.Web.Http, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)

据我目前所能确定的,当X509Certificate2 将在ChannelFactory 的呼叫中使用时,它似乎已经是Dispose()d。我也已经尝试将证书的新副本注入我的ChannelFactorys,但我仍然遇到同样的错误。有没有人在尝试从 Azure App Service 应用程序中使用 WCF 时遇到过类似的情况?

【问题讨论】:

你能贴出调用 WCF 服务的代码吗? 【参考方案1】:

在为此苦苦挣扎了几天后,我被其作者定向到this blog post。结合一些改进的异常处理和测试,我发现你需要指定加载标志 MachineKeySet |可为 X509Certificate2 的构造函数导出,否则证书将无法在 Azure 应用服务环境中正确加载。这是因为 Azure 应用服务 VM 不运行本地用户配置文件,因此没有可用的用户密钥存储。这与 X509Certificate2 的构造函数及其存储私钥的默认值有关。

【讨论】:

【参考方案2】:

我遇到了同样的问题。对我来说,问题是我的代码类似于:

using(var certificate = new X509Certificate2(privateKeyBytes, ...)

    ...
    return certificate;

证书似乎在被退回之前被处理掉了。删除using 声明后,它开始工作。

不确定是否与您的场景有关,但我认为值得在某处记录它:)

【讨论】:

以上是关于如何在 Azure 应用服务中将 X509Certificate2 与 WCF 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

在java中将x509证书写入PEM格式的字符串?

C#如何验证Root-CA-Cert证书(x509)链?

如何在Java中检索/计算X509证书的指纹?

X509Certificate 构造函数异常

docker从私有镜像库pull/push镜像问题:Error response from daemon: Get https://harbor.op.xxxx.com/v2/: x509: cert

如何从 Java 中的 X509Certificate 中提取 CN?