如何在 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。我也已经尝试将证书的新副本注入我的ChannelFactory
s,但我仍然遇到同样的错误。有没有人在尝试从 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 一起使用的主要内容,如果未能解决你的问题,请参考以下文章
docker从私有镜像库pull/push镜像问题:Error response from daemon: Get https://harbor.op.xxxx.com/v2/: x509: cert