c# - 在 Service Fabric 中通过 HTTPS 调用 WCF : The request was aborted: Could not create SSL/TLS secure channel

标签 c# wcf https ssl-certificate azure-service-fabric

我正在通过 HTTPS 调用 WCF 服务。 => 证书没问题。看截图:enter image description here

客户端证书安装在我的帐户和本地计算机下。 两者均可导出。

所以我有一段可以在控制台应用程序中运行的代码。当我在网络服务下运行控制台应用程序时,服务调用有效。

当我将此代码粘贴到 StatefullService(服务结构内部)中时,出现以下异常。

我已经验证了 ServicePointManager.SecurityProtocol 它是 System.Net.SecurityProtocolType.Tls | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls11 |控制台应用程序和服务 fabcric 中的 System.Net.SecurityProtocolType.Tls12

"System.ServiceModel.Security.SecurityNegotiationException: Could not establish secure channel for SSL/TLS with authority '********.cloudapp.azure.com'. ---> System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.\r\n at System.Net.HttpWebRequest.GetResponse()\r\n at System.ServiceModel.Channels.HttpChannelFactory1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)\r\n --- End of inner exception stack trace ---\r\n\r\nServer stack trace: \r\n at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)\r\n at System.ServiceModel.Channels.HttpChannelFactory1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)\r\n at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)\r\n at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)\r\n at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)\r\n at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)\r\n at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)\r\n\r\nException rethrown at [0]: \r\n at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)\r\n at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)\r\n at **********************************\r\n at ********************************* in ***********************.cs:line 75\r\n at *********************** in ***********************.cs:line 34\r\n at *********************** in ***********************.cs:line 20"

代码如下



            var binding = new BasicHttpBinding();
            binding.Security.Mode = BasicHttpSecurityMode.Transport;
            binding.Security.Transport = new HttpTransportSecurity
            {
                ClientCredentialType = HttpClientCredentialType.Certificate,
            };
            string endpoint = "https://********.cloudapp.azure.com/*****/SomeService.svc";
            var endpoint1 = new EndpointAddress(endpoint);

            var factory = new ChannelFactory(binding, endpoint);

            var clientCredentials = new ClientCredentials();
            clientCredentials.ClientCertificate.SetCertificate("CN=my-cn-name",
                System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine,
                System.Security.Cryptography.X509Certificates.StoreName.My);

            if (factory.Endpoint.EndpointBehaviors.Contains(typeof(ClientCredentials)))
            {
                factory.Endpoint.EndpointBehaviors.Remove(typeof(ClientCredentials));
            }

            factory.Endpoint.EndpointBehaviors.Add(clientCredentials);

            var channel = factory.CreateChannel();

            try
            {
                var result = channel.GetData(1);

                Console.WriteLine("Success");
                Console.ReadLine();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                Console.ReadLine();
            }

在服务结构中通过 HTTPS 调用 WCF 服务时缺少什么? 如果我禁用 HTTPS 协议(protocol)并在现有 WCF 服务上启用 HTTP 协议(protocol),我就可以连接。但出于显而易见的原因,我们需要 HTTPS。

编辑 1

测试:

  1. 使用 HttpClient 和 WebRequestHandler 作为 GET 调用服务以接收 HTML,这也适用于控制台应用程序。不在服务结构中。
  2. 从我的个人存储中删除了证书。控制台应用程序可以继续工作,因为它使用本地计算机存储(请参阅上面的代码示例)
  3. 通过 HTTPS 在 postman 中执行 SOAP 请求是可行的。

编辑2

按照这个答案https://serverfault.com/a/132791/135762 (用于网络服务)使其正常工作。

最佳答案

问题是网络服务帐户没有正确的访问权限来访问证书的私钥。

您可以通过两种方式解决这个问题。

第一个使用 powershell 和 setup.bat 来安装和配置证书。

在您的 Service Fabric 服务中,将 Setup.bat 添加到项目的根目录中。 编辑服务 list 并添加 setup entry point

<ExeHost> <Program>Setup.bat</Program> <WorkingFolder>CodePackage</WorkingFolder> </ExeHost>

bat 文件可能应该以更高的信任度运行。您可以在应用程序 list 中添加以下内容 在 ServiceManifestImport 内部:

<Policies> <RunAsPolicy CodePackageRef="Code" UserRef="SetupAdminUser" EntryPointType="Setup" /> </Policies>

在应用程序 list 的底部(在 xml 的根目录中)添加以下内容以管理员身份运行。 <Principals> <Users> <User Name="SetupAdminUser"> <MemberOf> <SystemGroup Name="Administrators" /> </MemberOf> </User> </Users> </Principals>

bat文件很简单: powershell.exe -ExecutionPolicy Bypass -Command ".\Scripts\Install-Certificates.ps1"

powershell 脚本可能如下所示


$pwd = ConvertTo-SecureString -String "YourPassword" -Force -AsPlainText

function Set-CertificatePermission
{
 param
 (
    [Parameter(Position=1, Mandatory=$true)]
    $cert ,

    [Parameter(Position=2, Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [string]$serviceAccount
 )


 # Specify the user, the permissions and the permission type
 $permission = "$($serviceAccount)","Read,FullControl","Allow"
 $accessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $permission;

 # Location of the machine related keys
 $keyPath = $env:ProgramData + "\Microsoft\Crypto\RSA\MachineKeys\";
 $keyName = $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName;
 $keyFullPath = $keyPath + $keyName;

 try
 {
    # Get the current acl of the private key
    $acl = (Get-Acl $keyFullPath)

    # Add the new ace to the acl of the private key
    $acl.AddAccessRule($accessRule);

    # Write back the new acl
    Set-Acl -Path $keyFullPath -AclObject $acl;
 }
 catch
 {
    throw $_;
 }
}

function Install-RootCA($path){
    Write-Host "Installing root certificate"

    Import-PfxCertificate -FilePath $path -CertStoreLocation "Cert:\LocalMachine\Root" -Password $pwd -Exportable
}

function Install-Certificate($path){
    Write-Host "Installing certificate"

     $cert = Import-PfxCertificate -FilePath $path -CertStoreLocation "Cert:\LocalMachine\My" -Password $pwd -Exportable
     Set-CertificatePermission $cert "NT AUTHORITY\NETWORK SERVICE"
}



Install-RootCA ".\Certificates\CARoot.pfx"
Install-Certificate ".\Certificates\ClientCert.pfx"

这将在受信任的根存储中安装证书(因为我们使用自签名证书),并在计算机帐户的个人存储中安装证书。 Service Fabric 的重要一点是它还为网络服务访问私钥设置了正确的权限。

第二种方法:使用mmc手动

  1. 按 Windows 键 + R
  2. 类型 mmc
  3. 文件 => 添加/删除管理单元
  4. 添加证书
  5. 选择计算机帐户
  6. 右键单击“受信任的根证书颁发机构\证书”
  7. 导入根证书 *.pfx(将其标记为可导出)
  8. 右键单击“个人\证书”
  9. 导入客户端证书 *.pfx(将其标记为可导出)
  10. 右键单击导入的客户端证书:所有任务 => 管理私钥
  11. 将网络服务添加为用户并赋予其完全控制权

关于c# - 在 Service Fabric 中通过 HTTPS 调用 WCF : The request was aborted: Could not create SSL/TLS secure channel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43473215/

相关文章:

c# - 如何使用 WCF 服务保存文件

spring boot https PKCS12 DerInputStream.getLength() : lengthTag=111, 太大

c# - 等待事件触发而不阻塞

c# - 异步等待死锁

.net - WCF 主机延迟 15 秒

wcf - WCF MSMQ 4.0 中的中毒消息处理

ssl - Erlang 无法连接到任何 HTTPS 网址

docker - Heroku和Google Cloud Run上的HTTP请求不同

c# - 从 Entity Framework 返回自定义对象 <List T> 并分配给对象数据源

c# - NServiceBus 消息从队列中删除,没有踪迹