在 Azure 应用服务上托管 WCF 不响应客户端应用服务

Posted

技术标签:

【中文标题】在 Azure 应用服务上托管 WCF 不响应客户端应用服务【英文标题】:Hosted WCF on azure app service not responding to client app service 【发布时间】:2021-11-08 00:00:07 【问题描述】:

我面临着 WCF 服务作为 Azure 上的应用服务托管的奇怪问题。 不知何故,此客户端应用服务无法与 Azure 应用服务通信。

我已经部署了测试(示例)应用服务和测试示例客户端应用服务,它们之间的通信非常完美。

以下是例外:

" 管理前端组件注册期间出现问题! 2021/09/12 08:59:08.111 [错误] System.ServiceModel.CommunicationException:向https://ahponeserver.azurewebsites.net/AHPFrontendService.svc/FES3 发出 HTTP 请求时出错。这可能是由于在 HTTPS 情况下未使用 HTTP.SYS 正确配置服务器证书。这也可能是由于客户端和服务器之间的安全绑定不匹配造成的。 ---> System.Net.WebException:底层连接已关闭:发送时发生意外错误。 ---> System.IO.IOException: Unable to read data from the transport connection: 一个现有的连接被远程主机强行关闭。 ---> System.Net.Sockets.SocketException: 现有连接被远程主机强行关闭”

以下是 WCF Server 的 Web.config。

    <?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
    <add key="CryptoKey" value="9878237hsde8zh3299h43h" />
    <add key="AppTitle" value="Service in DEV" />
    <add key="ahpDefaultISOCode" value="EN" />
    <add key="ahpExposeTestController" value="true"/>
    <!--Database Settings-->
    <add key="databaseServer" value="APDV0710" />
    <add key="database" value="AHPOneConfig" />
    <add key="databaseUser" value="AHPOneConfigD13" />
    <add key="databaseUserPassword" value="qx5ZB2xVfEf5gnDtIdzRGAxcpA9g6fNvNdv63gxR2Bo=" />
    <add key="AllowActivation" value="uzuftuGUH3H6bvn41IB7x1Xo/v72atlXdE543qcSRlI=" />
  </appSettings>
 
 
  <system.web>
    <compilation debug="true" targetFramework="4.7.2" />
    <httpRuntime targetFramework="4.7.2" />
  </system.web>

  <system.serviceModel>
    <diagnostics>
      <messageLogging logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />
    </diagnostics>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBindingWindows">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Windows" />
          </security>
        </binding>
      </basicHttpBinding>

          <wsHttpBinding>
            <binding name="wsHttpBindingUsername">
              <reliableSession enabled="true" inactivityTimeout="00:30:00" />
              <security mode="Message">
                <message clientCredentialType="UserName" />
              </security>
            </binding>

            <binding name="wsHttpBindingWindows">
              <security mode="Transport">
                <transport clientCredentialType="None"></transport>
                <!--message clientCredentialType="Windows" establishSecurityContext="false" negotiateServiceCredential="false" /-->
              </security>
            </binding>

            <binding name="wsHttpEndpointBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
              <security mode="TransportWithMessageCredential">
                <transport clientCredentialType="None" />
                <message clientCredentialType="UserName" />
              </security>
            </binding>

            <!-- old -->
            <!--<binding name="wsHttpBindingWindows">
              <security mode="Transport">
                <transport clientCredentialType="Windows"/>
              </security>
            </binding>-->
          </wsHttpBinding>

      <!-- Start new entry for external interface -->
      <webHttpBinding>
        <binding>
          <security mode="Transport" />
        </binding>
      </webHttpBinding>
      <!-- End new entry for external interface -->

    </bindings>   
    
    <behaviors>

      <!-- Start new entry for external interface  -->
      <endpointBehaviors>
        <behavior name="restfulBehavior">
          <webHttp />
        </behavior>
      </endpointBehaviors>
      <!-- End new entry for external interface -->

      <serviceBehaviors>
        <!-- Start new entry for external interface -->
        <behavior name="restfullServiceBehavior">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
        <!-- End new entry for external interface -->

        <!-- Custom Authentication Windows -->
        <behavior name="windowsValidation2">
          <serviceThrottling maxConcurrentCalls="300" maxConcurrentSessions="2000" maxConcurrentInstances="2000" />
          <serviceMetadata httpGetEnabled="True" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>

        <!-- Custom Authentication UsernamePassword -->
        <behavior name="CustomUsernameValidation2">
          <serviceThrottling maxConcurrentCalls="300" maxConcurrentSessions="2000" maxConcurrentInstances="2000" />
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceCredentials>
            <!--Specify the Custom Authentication policy that will be used and add the policy location-->
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="ahpFrontendWCFService.ServiceImplementation.UserAuthentication,ahpFrontendWCFService" />
          </serviceCredentials>
        </behavior>

        <behavior>
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <services>
      
       <service name="ahpFrontendWCFService.AHPFrontendServiceWindows" 
               behaviorConfiguration="windowsValidation2">
        <endpoint name="FES2"
                  address="FES2"
                  binding="wsHttpBinding"
                  contract="ahpFrontendWCFService.IAHPFrontendServiceV1"
                  bindingConfiguration="wsHttpBindingWindows"/>
      </service>

      <service name="ahpFrontendWCFService.AHPFrontendService"
               behaviorConfiguration="CustomUsernameValidation2">
        <endpoint name="FES3"
                  address="FES3"
                  binding="wsHttpBinding"
                  bindingConfiguration="wsHttpEndpointBinding"
                  contract="ahpFrontendWCFService.IAHPFrontendServiceV1"/>
      </service>

       <!--Start new entry for reporting interface--> 
     <service name="ahpFrontendWCFService.AHPReportingService" 
               behaviorConfiguration="CustomUsernameValidation2">
        <endpoint name="FES3"
                  address="FES3"
                  binding="wsHttpBinding"
                  contract="ahpFrontendWCFService.IAHPReportingService"
                  bindingConfiguration="wsHttpEndpointBinding" />
      </service>
       <!--End new entry for reporting interface 

       Start new entry for external interface--> 
      <service name="ahpFrontendWCFService.AHPExternalService"
               behaviorConfiguration="restfullServiceBehavior">
        <endpoint binding="webHttpBinding"
                  contract="ahpFrontendWCFService.IAHPExternalService"
                  behaviorConfiguration="restfulBehavior"/>
      </service>
       <!--End new entry for external interface 

       Start new entry for external interface--> 
      <service name="ahpFrontendWCFService.AHPSetupService"
               behaviorConfiguration="restfullServiceBehavior">
        <endpoint binding="webHttpBinding"
                  contract="ahpFrontendWCFService.IAHPSetupService"
                  behaviorConfiguration="restfulBehavior"/>
      </service>
      <!-- End new entry for external interface -->


    </services>

  
    <protocolMapping>
      <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="true" />
  </system.webServer>

  <location path="AHPOne/Proxy">
    <system.webServer>
      <handlers>
        <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
        <remove name="OPTIONSVerbHandler" />
        <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
      </handlers>
      <httpProtocol>
        <customHeaders>
          <!-- <add name="Access-Control-Allow-Origin" value="*" />  this header is added through api controller class -->
          <add name="Access-Control-Allow-Headers" value="Authorization" />
          <add name="Access-Control-Allow-Credentials" value="true" />
        </customHeaders>
      </httpProtocol>
    </system.webServer>
  </location>

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

以下是客户端应用服务的 web.config(仅粘贴该 web.config 中的相关部分)

 <system.serviceModel>
<!-- username binding-->
<bindings>
  <wsHttpBinding>
    <binding name="FES3" maxBufferPoolSize="500000000" maxReceivedMessageSize="500000000" sendTimeout="00:20:00">
      <security mode="TransportWithMessageCredential">
        <transport clientCredentialType="None"/>
        <message clientCredentialType="UserName"/>
      </security>
    </binding>
  </wsHttpBinding>
</bindings>
<client>
  <endpoint address="https://ahponeserver.azurewebsites.net/AHPFrontendService.svc/FES3" binding="wsHttpBinding" bindingConfiguration="FES3"
    contract="Ahp.Frontend.Shared.WCFProxyClasses.ahpFrontendService" name="FES3"/>
</client>

我不知道如何找出问题所在。有什么办法可以解决这个问题?

是否需要设置一些证书? 配置有问题吗?

如果有一些想法会很高兴。

【问题讨论】:

【参考方案1】:

如果您的服务器已更新到 TLS V1.2 并使用 SSL 标准连接,您可以尝试以下步骤:

if (System.Net.ServicePointManager.SecurityProtocol == (SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls))
    System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

【讨论】:

我需要把这段代码sn-p放在哪里?在哪里可以检查 TLS V1.2 和 SSL 连接?

以上是关于在 Azure 应用服务上托管 WCF 不响应客户端应用服务的主要内容,如果未能解决你的问题,请参考以下文章

在 IIS 上托管 WCF 后出现“请求错误”

IIS 上托管的 WCF 服务和 IIS 上的客户端网站

访问本地 IIS 上托管的 WCF 服务时出错:“相对 URI 不支持此操作。”

在服务器上托管 WCF 服务后创建和杀死空线程

如何在 Azure 上托管 html 应用程序

从 Web 客户端调用 Microsoft Bot Framework 机器人,无需在 Azure 上托管