Skip to main content
 首页 » 编程设计

c#之从 IIS 托管的应用程序通过 SSL 访问 Web 服务时出错

2024年02月20日29zhujiabin

这已经困扰我三天了,经过大量谷歌搜索后,我决定发布一个问题。我有一个 WCF 服务应用程序(“本地服务”),它安全地连接到“远程 Web 服务”(Java)(双向证书身份验证)。

我的服务端配置:

<system.serviceModel> 
  <bindings> 
      <basicHttpBinding> 
          <binding name="IhAdapterPortBinding" closeTimeout="00:01:00" 
              openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" 
              allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" 
              maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" 
              messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" 
              useDefaultWebProxy="true"> 
              <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" 
                  maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
              <security mode="Transport"> 
                  <transport clientCredentialType="Certificate" proxyCredentialType="None" 
                      realm="" /> 
                  <message clientCredentialType="UserName" algorithmSuite="Default" /> 
              </security> 
          </binding>               
      </basicHttpBinding> 
  </bindings> 
  <client> 
      <endpoint address="https://someserver.com:8085/IhAdapter" binding="basicHttpBinding" 
          bindingConfiguration="IhAdapterPortBinding" contract="IHAdapter.IhAdapter" 
          name="IhAdapterPort" behaviorConfiguration="IHAdapterEndpointBehavior" />        
  </client> 
<services> 
  <service name="SomeCompany.SomeService"> 
    <endpoint address="" binding="basicHttpBinding" 
      contract="SomeCompany.ISomeService" /> 
  </service> 
</services> 
<behaviors> 
  <endpointBehaviors> 
    <behavior name="IHAdapterEndpointBehavior"> 
             <clientCredentials> 
                  <clientCertificate storeLocation="LocalMachine" storeName="My" findValue="123...abc" x509FindType="FindByThumbprint"/> 
                  <serviceCertificate> 
                       <authentication certificateValidationMode="None" revocationMode="NoCheck"/> 
                  </serviceCertificate> 
             </clientCredentials> 
        </behavior> 
  </endpointBehaviors> 
  <serviceBehaviors> 
    <behavior name=""> 
      <serviceMetadata httpGetEnabled="true" /> 
      <serviceDebug includeExceptionDetailInFaults="true" /> 
    </behavior> 
  </serviceBehaviors> 
</behaviors> 
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> 

现在来解决问题。在 Visual Studio Web Development Server 中托管服务或从本地测试客户端 (.exe) 调用远程服务时,调用成功。但是当本地服务由 IIS 托管(localhost 或其他一些服务器 IIS)时,我得到异常:

无法使用权​​限“https://someserver.com:8085”为 SSL/TLS 建立安全通道'

内部异常:

请求已中止:无法创建 SSL/TLS 安全通道。

到目前为止我尝试或检查的内容:

  • 正确的证书存储位置(本地计算机,而不是用户)
  • 私钥权限(进入 MMC,找到证书,右键单击,所有任务,管理私钥,设置为所有人的所有权限)
  • 将 IIS 应用程序用户(Connect As)设置为具有管理权限的本地用户

还有一件事:当前的远程服务器证书是为另一个主机名颁发的,所以我必须以编程方式覆盖验证。因此,要在本地服务中创建远程服务对象,我有以下几行代码:

ServicePointManager.Expect100Continue = true; 
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; 
ServicePointManager.ServerCertificateValidationCallback = ((senderParam, certificate, chain, sslPolicyErrors) => true); 
 
IHAdapter.IhAdapterClient ihAdapter = new IHAdapter.IhAdapterClient(); 
 
ihAdapter.SomeMethod(parameters); // the exception gets thrown here 

我还缺少什么?有什么想法、指示吗?

请您参考如下方法:

好的,回答我自己的问题。

基于此链接:How to give ASP.NET access to a private key in a certificate in the certificate store? 我解决了我的问题。

我的解决方案的关键是这个检查 list :

  1. 创建/购买证书。确保它有私钥。
  2. 将证书导入“本地计算机”帐户。最好使用证书 MMC。 确保选中“允许私钥 导出”
  3. 基于此,IIS 7.5 应用程序池的标识使用以下之一:
    • IIS 7.5 网站在 ApplicationPoolIdentity 下运行。使用证书 MMC,将“IIS AppPool\AppPoolName”添加到“本地计算机\个人”中证书的完全信任。将“AppPoolName”替换为您的应用程序池的名称。
    • IIS 7.5 网站在 NETWORK SERVICE 下运行。使用证书 MMC,将“网络服务”添加到对“本地计算机\个人”中证书的完全信任。
    • IIS 7.5 网站在“MyIISUser”本地计算机用户帐户下运行。使用证书 MMC,将“MyIISUser”(一个新的本地计算机用户帐户)添加到对“本地计算机\个人”中证书的完全信任。

我几乎肯定做了所有这些事情,但显然从来没有同时做过。希望这对其他人有帮助。无论如何,感谢您提供的所有帮助。