繁体   English   中英

从 Azure Function 应用程序调用 WCF 服务

[英]Calling WCF Service from Azure Function App

我最近将我们的 function 应用程序之一从 .NET Core 3.1 重写为 .NET 6 并实施了依赖注入。 我们的 function 应用程序调用 WCF web 服务端点,以实现我们平台中的一些共享功能。

我们的旧 .NET Core 3.1 function 应用程序用于“注册”web 服务,如下所示:

public static IWCFWebService GetWebService()
{
   string endpointUrl = Environment.GetEnvironmentVariable("WebServiceEndpoint");
   string certString = Environment.GetEnvironmentVariable("WebServiceCert");

   return new WCFWebServiceClient(endpointUrl, certString);
}

而 WebServiceCert 变量实际上只是我们环境配置中的散列证书字符串。 它运作良好。

WCFWebServiceClient 构造函数如下:

public WCFWebServiceClient(string endpointUrl, string certString) :
   base(WCFWebServiceClient.GetDefaultBinding(), 
   WCFWebServiceClient.GetDefaultEndpointAddress())
{
   EndpointUrl = endpointUrl;
   this.Endpoint.Address = new System.ServiceModel.EndpointAddress(endpointUrl);
   this.Endpoint.Name = EndpointConfiguration.BasicHttpBinding_IWCFWebService.ToString();
   ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
   this.ClientCredentials.ClientCertificate.Certificate = GetCertificate(certString);
}

在将应用程序重写为 .NET 6 时,我想以一种我们实际使用原始证书而不是散列字符串的方式注册 WCF 服务。 我注册如下:

var host = new HostBuilder()
   .ConfigureFunctionsWorkerDefaults()
   .ConfigureAppConfiguration(config => config
      .SetBasePath(Directory.GetCurrentDirectory())
      .AddEnvironmentVariables())
   .ConfigureServices(services =>
   {
      services.AddTransient<IWCFWebService>(provider =>
      {
         var endpoint = Environment.GetEnvironmentVariable("WebServiceEndpoint");
         var certificate = new 
            X509Certificate2(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + 
            @"\Certificates\Webservice_Client.pfx", "password");

         return new WCFWebServiceClient(endpoint, certificate);
      });
   }

实际的 raw.pfx 证书在项目中并被构建并复制到 output 文件夹。

我为 WCFWebServiceClient 构造函数编写了一个重载,以获取 X509Certificate 而不是 hash 字符串。 它是这样的:

public WCFWebServiceClient(string endpointUrl, X509Certificate2 certificate) :
   base(WCFWebServiceClient.GetDefaultBinding(), 
      WCFWebServiceClient.GetDefaultEndpointAddress())
{
   EndpointUrl = endpointUrl;
   this.Endpoint.Address = new System.ServiceModel.EndpointAddress(endpointUrl);
   this.Endpoint.Name = EndpointConfiguration.BasicHttpBinding_IWCFWebService.ToString();
   ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
   this.ClientCredentials.ClientCertificate.Certificate = certificate;
}

自从这个实施以来,我们得到了非常复杂的结果。 我们经常在 Application Insights 日志中看到以下错误:

异常:Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException:密钥集不存在

这显然表明证书存在某种错误。 它似乎与任何用户权限或任何内容无关,因为自从我们在 .NET Core 3.1 上工作以来,这些权限没有改变。 证书没有更改或移动。 我们可以在本地调试使其正常工作,这表明证书仍然有效并且用户权限是正确的。 证书安装在正确的服务器上,因为我们有其他应用程序和代码调用相同的 web 服务(尽管是在旧版本的框架上,而不是 .NET 核心)。 但是,我们在已部署的 function 应用程序的日志中收到此错误,但并不一致。 有时 function 会起作用,有时会抛出此错误。

由于它不一致,我的第一个想法是我注册它的生命周期 scope 可能不正确,所以我将它从 Transient 更改为 Scoped 并且仍然出现错误。 我仍然可以尝试 Singleton,但如果这是正确的解决方案,我会很谨慎,而且我已经在线阅读到 Singleton 调用 WCF 不是正确的方法。 (我仍然不确定何时使用哪些范围)。

由于这不是证书问题,也不是凭据问题,而且我们有时可以让它在已部署的 function 应用程序上运行,但不是一直都可以运行,所以除了尝试更改 scope 之外,我不知道是什么原因导致的到 Singleton?

谁能帮忙?

您可以尝试以下操作:

  • 以管理员身份运行你的程序
  • 如果是部署在IIS的web app -> 然后在Certificate权限中添加IIS_IUSRS。 个人中的Select证书,右击->管理私钥->添加用户。
  • 如果处于调试状态,请以管理员模式运行 Visual Studio 以解决此问题
  • 运行 APP CMD 命令以将用户配置文件设置为为您的应用程序池加载。方法来源这篇文章


一些有用的链接
CryptographicException 'Keyset does not exist',但只能通过 WCF
WindowsCryptographicException:密钥集不存在

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM