简体   繁体   English

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

[英]Calling WCF Service from Azure Function App

I recently rewrote one of our function apps from .NET Core 3.1 to .NET 6 and implementing dependency injection.我最近将我们的 function 应用程序之一从 .NET Core 3.1 重写为 .NET 6 并实施了依赖注入。 Our function app calls a WCF web service endpoint for several bits of shared functionality that we have in our platforms.我们的 function 应用程序调用 WCF web 服务端点,以实现我们平台中的一些共享功能。

Our old .NET Core 3.1 function app used to "register" the web service as follows:我们的旧 .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);
}

whereas the WebServiceCert variable was actually just the hashed cert string in our environmental config.而 WebServiceCert 变量实际上只是我们环境配置中的散列证书字符串。 It worked fine.它运作良好。

The WCFWebServiceClientconstructor was as follows: 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);
}

In rewriting the app to .NET 6, I wanted to register the WCF service in a way that we were actually consuming the raw certificate and not the hashed string.在将应用程序重写为 .NET 6 时,我想以一种我们实际使用原始证书而不是散列字符串的方式注册 WCF 服务。 I registered it as follows:我注册如下:

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

with the actual raw.pfx certificate being in the project and being built and copied to the output folder.实际的 raw.pfx 证书在项目中并被构建并复制到 output 文件夹。

I wrote an overload for the WCFWebServiceClient constructor to take the X509Certificate instead of the hash string.我为 WCFWebServiceClient 构造函数编写了一个重载,以获取 X509Certificate 而不是 hash 字符串。 It is as follows:它是这样的:

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

Ever since this implementation, we've had very mixed results.自从这个实施以来,我们得到了非常复杂的结果。 We're often seeing the following error in our Application Insights Logs:我们经常在 Application Insights 日志中看到以下错误:

Exception: Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Keyset does not exist异常:Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException:密钥集不存在

which obviously points to some sort of error with the certificate.这显然表明证书存在某种错误。 It doesn't seem to be related to any user permissions or anything because those have not changed since we had it working on .NET Core 3.1.它似乎与任何用户权限或任何内容无关,因为自从我们在 .NET Core 3.1 上工作以来,这些权限没有改变。 The certificate hasn't changed or moved.证书没有更改或移动。 We can get it to work fine wehn debugging locally, which indicates the certificate is still valid and the user permissions are correct.我们可以在本地调试使其正常工作,这表明证书仍然有效并且用户权限是正确的。 The certificate is installed on the proper servers because we have other applications and code calling the same web service (albeit on a older version of Framework and not .NET Core).证书安装在正确的服务器上,因为我们有其他应用程序和代码调用相同的 web 服务(尽管是在旧版本的框架上,而不是 .NET 核心)。 However, we get this error in our logs on the deployed function app, but not consistently.但是,我们在已部署的 function 应用程序的日志中收到此错误,但并不一致。 Sometimes the function will work, sometimes it will throw this error.有时 function 会起作用,有时会抛出此错误。

Since it wasn't consistent, my first thought is that maybe the lifetime scope I was registering it under was incorrect, so I changed it from Transient to Scoped and still appear to get the error.由于它不一致,我的第一个想法是我注册它的生命周期 scope 可能不正确,所以我将它从 Transient 更改为 Scoped 并且仍然出现错误。 I could still try Singleton, but I'm wary if that's the correct solution and I've read online that a Singleton call to a WCF isn't the correct way.我仍然可以尝试 Singleton,但如果这是正确的解决方案,我会很谨慎,而且我已经在线阅读到 Singleton 调用 WCF 不是正确的方法。 (I'm still a little uncertain as to when to use which scopes). (我仍然不确定何时使用哪些范围)。

Since it's not a certificate issue and not a credentials issue, and we can get it to work sometimes but not all the time on the deployed function app, I'm out of ideas as to what could cause this outside of TRYING to change the scope to Singleton?由于这不是证书问题,也不是凭据问题,而且我们有时可以让它在已部署的 function 应用程序上运行,但不是一直都可以运行,所以除了尝试更改 scope 之外,我不知道是什么原因导致的到 Singleton?

Can anyone help?谁能帮忙?

You can try the following:您可以尝试以下操作:

  • Run your program as Administrator以管理员身份运行你的程序
  • If it is web app deployed in IIS -> then add the IIS_IUSRS to the Certificate permissions.如果是部署在IIS的web app -> 然后在Certificate权限中添加IIS_IUSRS。 Select certificate in Personal, Right Click-> Manage Private Keys -> Add the user.个人中的Select证书,右击->管理私钥->添加用户。
  • Run Visual Studio in Admin mode if in Debug to get this problem sorted out如果处于调试状态,请以管理员模式运行 Visual Studio 以解决此问题
  • Run the APP CMD command to set the user profile to load as true for your app pool.Method source this post .运行 APP CMD 命令以将用户配置文件设置为为您的应用程序池加载。方法来源这篇文章


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

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

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