从Azure函数应用程序调用WCF服务
我最近将我们的一个功能应用程序从.NET Core 3.1重写为.NET 6并实现依赖注入。我们的功能应用调用WCF Web服务端点,用于我们在平台中拥有的几个共享功能。
我们的旧.NET CORE 3.1功能应用程序用于“注册” Web服务,如下所示:
public static IWCFWebService GetWebService()
{
string endpointUrl = Environment.GetEnvironmentVariable("WebServiceEndpoint");
string certString = Environment.GetEnvironmentVariable("WebServiceCert");
return new WCFWebServiceClient(endpointUrl, certString);
}
而WebServiceCert变量实际上只是我们环境配置中的Hashed Cert字符串。它运行良好。
WCFWEBServiceClientConstructor如下:
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时,我想以实际上消耗原始证书而不是Hashed字符串的方式注册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证书正在项目中,并将被构建并复制到输出文件夹中。
我为WCFWEBServiceClient构造函数编写了一个过载,以使用X509Certificate而不是哈希字符串。如下:
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;
}
自从此实施以来,我们的结果非常不同。我们经常在应用程序见解日志中看到以下错误:
例外: internal.cryptography.cryptothrowhelper+windowscryptographicexception: Keyset不存在
,显然指出了证书的某种错误。它似乎与任何用户权限或其他任何内容无关,因为自从我们将其处理.NET Core 3.1以来,它们没有更改。证书尚未更改或移动。我们可以使其正常工作,Wehn在本地调试,这表明证书仍然有效并且用户权限正确。证书安装在适当的服务器上,因为我们还有其他应用程序和代码调用相同的Web服务(尽管在较旧版本的框架上,而不是.NET Core)。但是,我们在已部署的功能应用程序上的日志中获得此错误,但并非一致。有时该功能会起作用,有时会引发此错误。
由于它并不一致,所以我的第一个想法是,我正在注册它的终身范围是不正确的,所以我将其从瞬态更改为范围,似乎仍然会遇到错误。我仍然可以尝试Singleton,但是如果这是正确的解决方案,我会保持警惕,并且我在网上读到Singleton呼叫WCF不是正确的方法。 (我仍然有点不确定何时使用范围)。
由于它不是证书问题,也不是凭据问题,我们有时可以使其工作,但不是一直在部署的功能应用程序上工作,所以我对可能导致此范围之外的原因有什么想法要辛格尔顿?
谁能帮忙?
I recently rewrote one of our function apps from .NET Core 3.1 to .NET 6 and implementing dependency injection. Our function app calls a WCF web service endpoint for several bits of shared functionality that we have in our platforms.
Our old .NET Core 3.1 function app used to "register" the web service as follows:
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. It worked fine.
The WCFWebServiceClientconstructor was as follows:
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. 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.
I wrote an overload for the WCFWebServiceClient constructor to take the X509Certificate instead of the hash string. 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:
Exception:
Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException:
Keyset does not exist
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. 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). However, we get this error in our logs on the deployed function app, but not consistently. Sometimes the function will work, sometimes it will throw this error.
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. 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. (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?
Can anyone help?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以尝试以下操作:
证书许可。选择个人证书
点击 - &gt;管理私钥 - &GT;添加用户。
整理
您的应用程序池源这篇文章。
一些有用的链接
cyptographiceCeption'keyset'Keyset'''''''' a>
windowsCryptographingCographiceXception:Keysets不存在
You can try the following:
Certificate permissions. Select certificate in Personal, Right
Click-> Manage Private Keys -> Add the user.
sorted out
your app pool.Method source this post.
some useful links
CryptographicException 'Keyset does not exist', but only through WCF
WindowsCryptographicException: Keyset does not exist