在 Service Fabric 中通过 HTTPS 调用 WCF:请求已中止:无法创建 SSL/TLS 安全通道

2023-12-14

I'm calling a WCF service over HTTPS. => The certificates are ok. See screenshot: enter image description here

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

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

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

我已经验证了ServicePointManager.SecurityProtocol It's System.Net.SecurityProtocolType.Tls | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls12在控制台应用程序和服务结构中。

“System.ServiceModel.Security.SecurityNegotiationException:无法使用权​​限“********.cloudapp.azure.com”建立 SSL/TLS 的安全通道。 ---> System.Net.WebException:请求是已中止: 无法创建 SSL/TLS 安全通道。\r\n 位于 System.Net.HttpWebRequest.GetResponse()\r\n 位于 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超时)\r\n在System.ServiceModel.Channels.RequestChannel.Request(消息消息,TimeSpan超时)\r\n在System.ServiceModel.Dispatcher.RequestChannelBinder.Request(消息消息, TimeSpan 超时)\r\n 在 System.ServiceModel.Channels.ServiceChannel.Call(字符串操作、布尔单向、ProxyOperationRuntime 操作、Object[] ins、Object[] outs、TimeSpan 超时)\r\n 在 System.ServiceModel.Channels .ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime 操作)\r\n 在 System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage 消息)\r\n\r\n在 [0] 处重新引发异常: \r\n 在 System. Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg,IMessage retMsg)\r\n 在 System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData,Int32 类型)\r\n 在 ****** **************************\r\n 于 ***************** ************** 在 **********************.cs: 第 75 行\r\n 处********************** 在 **********************.cs 中:第 34 行\r\n 位于 ********************** 在 ****************** ****.cs:第 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 协议并在现有 WCF 服务上启用 HTTP 协议,我就可以连接。但出于显而易见的原因,我们需要 HTTPS。

Edit 1

Tested:

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

Edit 2

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


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

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

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

在您的 Service Fabric 服务中,将 Setup.bat 添加到项目的根目录中。 编辑服务清单并添加一个设置入口点

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

bat 文件可能应该以更高的信任度运行。您可以在以下内容中添加申请清单在 ServiceManifestImport 内部:

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

在应用程序清单的底部(在 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. Type mmc
  3. 文件 => 添加/删除管理单元
  4. 添加证书
  5. 选择计算机帐户
  6. 右键单击“受信任的根证书颁发机构\证书”
  7. 导入根证书*.pfx(将其标记为可导出)
  8. 右键单击个人\证书
  9. 导入客户端证书*.pfx(将其标记为可导出)
  10. 右键单击导入的客户端证书:所有任务 => 管理私钥
  11. 添加网络服务作为用户并给予其完全控制权
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Service Fabric 中通过 HTTPS 调用 WCF:请求已中止:无法创建 SSL/TLS 安全通道 的相关文章

  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • 为什么 C# Array.BinarySearch 这么快?

    我已经实施了一个很简单用于在整数数组中查找整数的 C 中的 binarySearch 实现 二分查找 static int binarySearch int arr int i int low 0 high arr Length 1 mid
  • 秒表有最长运行时间吗?

    多久可以Stopwatch在 NET 中运行 如果达到该限制 它会回绕到负数还是从 0 重新开始 Stopwatch Elapsed返回一个TimeSpan From MSDN https learn microsoft com en us
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 为什么编译时浮点计算可能不会得到与运行时计算相同的结果?

    In the speaker mentioned Compile time floating point calculations might not have the same results as runtime calculation
  • 如何将带有 IP 地址的连接字符串放入 web.config 文件中?

    我们当前在 web config 文件中使用以下连接字符串 add name DBConnectionString connectionString Data Source ourServer Initial Catalog ourDB P
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • 测试用例执行完成后,无论是否通过,如何将测试用例结果保存在变量中?

    我正在使用 NUNIT 在 Visual Studio 中使用 Selenium WebDriver 测试用例的代码是 我想在执行测试用例后立即在变量中记录测试用例通过或失败的情况 我怎样才能实现这一点 NUnit 假设您使用 NUnit
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写

随机推荐