c# - 带有服务结构的 SOAP - Https 和 Http 绑定(bind)

标签 c# wcf azure-service-fabric

我目前正在开发一个 service fabric 应用程序,它将公开一个 soap 监听器,该监听器将被另一个应用程序使用

我一直收到错误提示

Could not find a base address that matches scheme https for the endpoint with binding CustomBinding. Registered base address schemes are []

这里是CreateServiceInstanceListener方法

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        var serviceInstanceListers = new List<ServiceInstanceListener>()
        {
            new ServiceInstanceListener(context =>
            {
                return CreateSoapListener(context);
            })
            ,
            new ServiceInstanceListener(context =>
            {
                return CreateSoapHTTPSListener(context);
            }),
        };
        return serviceInstanceListers;
    }


    private static ICommunicationListener CreateSoapHTTPSListener(StatelessServiceContext context)
    {
        string host = context.NodeContext.IPAddressOrFQDN;
        var endpointConfig = context.CodePackageActivationContext.GetEndpoint("SecureServiceEndpoint");
        int port = endpointConfig.Port;
        string scheme = endpointConfig.Protocol.ToString();

        string uri = string.Format(CultureInfo.InvariantCulture, "{0}://{1}:{2}/MyService/", scheme, host, port);
        var listener = new WcfCommunicationListener<IServiceInterface>(
            serviceContext: context,
            wcfServiceObject: new Service(),
            listenerBinding: new BasicHttpsBinding(BasicHttpsSecurityMode.Transport),
            address: new EndpointAddress(uri)
        );

        // Check to see if the service host already has a ServiceMetadataBehavior
        ServiceMetadataBehavior smb = listener.ServiceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
        // If not, add one
        if (smb == null)
        {
            smb = new ServiceMetadataBehavior();
            smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
            smb.HttpsGetEnabled = true;
            smb.HttpsGetUrl = new Uri(uri);

            listener.ServiceHost.Description.Behaviors.Add(smb);
        }
        return listener;
    }

    private static ICommunicationListener CreateSoapListener(StatelessServiceContext context)
    {
        string host = context.NodeContext.IPAddressOrFQDN;
        var endpointConfig = context.CodePackageActivationContext.GetEndpoint("ServiceEndpoint");
        int port = endpointConfig.Port;
        string scheme = endpointConfig.Protocol.ToString();

        string uri = string.Format(CultureInfo.InvariantCulture, "{0}://{1}:{2}/MyService/", scheme, host, port);
        var listener = new WcfCommunicationListener<IServiceInterface>(
            serviceContext: context,
            wcfServiceObject: new Service(),
            listenerBinding: new BasicHttpBinding(BasicHttpSecurityMode.None),
            address: new EndpointAddress(uri)
        );

        // Check to see if the service host already has a ServiceMetadataBehavior
        ServiceMetadataBehavior smb = listener.ServiceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
        // If not, add one
        if (smb == null)
        {
            smb = new ServiceMetadataBehavior();
            smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
            smb.HttpGetEnabled = true;
            smb.HttpGetUrl = new Uri(uri);

            listener.ServiceHost.Description.Behaviors.Add(smb);
        }
        return listener;
    }

这是 app.config(抱歉,如果有无用的条目,我是从现有的 WCF 应用程序复制的)

    <?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
  </startup>

  <system.web>
    <customErrors mode="On"></customErrors>
    <compilation debug="true" targetFramework="4.6.2"/>
    <httpModules>
      <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web"/>
    </httpModules>
    <machineKey decryption="AES" decryptionKey="decryptionkey" validation="SHA1" validationKey="validationkey"/>
  </system.web>
  <system.serviceModel>
    <diagnostics wmiProviderEnabled="true">
      <messageLogging logEntireMessage="true" logKnownPii="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true"/>
      <endToEndTracing propagateActivity="true" activityTracing="true" messageFlowTracing="true"/>
    </diagnostics>
    <bindings>
      <customBinding>
        <binding name="HubBinding">
          <security defaultAlgorithmSuite="Basic256Sha256Rsa15" allowSerializedSigningTokenOnReply="true" authenticationMode="MutualCertificateDuplex" securityHeaderLayout="Lax" messageProtectionOrder="EncryptBeforeSign" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"/>
          <textMessageEncoding messageVersion="Default"/>
          <httpsTransport maxReceivedMessageSize="1073741824"/>
        </binding>
        <binding name="AuthorityCustomBinding">
          <security defaultAlgorithmSuite="Basic256Sha256Rsa15" allowSerializedSigningTokenOnReply="true" authenticationMode="MutualCertificateDuplex" securityHeaderLayout="Lax" messageProtectionOrder="EncryptBeforeSign" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"/>
          <textMessageEncoding messageVersion="Default"/>
          <httpsTransport maxReceivedMessageSize="1073741824"/>
        </binding>
        <binding name="CustomBinding_IServiceInterface">
          <security/>
          <textMessageEncoding/>
          <httpsTransport/>
        </binding>

      </customBinding>
    </bindings>
    <services>
      <service name="MyApp.ProductServiceManufacturer" behaviorConfiguration="ManufacturerBehaviour">
        <endpoint address="" name="ManufacturerProductService" binding="customBinding" bindingConfiguration="HubBinding" contract="MyApp.IProductServiceV20161"/>
      </service>

    </services>
    <client>
      <endpoint address="https://serverurl:8088/IServiceInterface/Service.svc" behaviorConfiguration="HubManufacturerBehavior" binding="customBinding" bindingConfiguration="AuthorityCustomBinding" contract="Service.IServiceInterface" name="CustomBinding_IProductServiceManufacturerV20161">
        <identity>
          <dns value="ServerCert"/>
        </identity>
      </endpoint>

    </client>
    <behaviors>
      <endpointBehaviors>
        <behavior name="HubManufacturerBehavior">
          <clientCredentials>
            <clientCertificate findValue="XXXXXX" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint"/>
            <serviceCertificate>
              <defaultCertificate findValue="XXXXXX" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint"/>
            </serviceCertificate>
          </clientCredentials>
        </behavior>
        <behavior name="MyApp.ReportingServiceManufacturerAspNetAjaxBehavior">
          <enableWebScript/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="ManufacturerBehaviour">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceCredentials>
            <serviceCertificate findValue="XXXXXX" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint"/>
          </serviceCredentials>
          <serviceSecurityAudit auditLogLocation="Application" suppressAuditFailure="true" serviceAuthorizationAuditLevel="Failure" messageAuthenticationAuditLevel="Failure"/>
        </behavior>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
    <extensions>
      <bindingElementExtensions>
        <add name="securityBindingElementExtension" type="MyApp.BindingExtensions.SecurityBindingElementExtension, MyApp"/>
      </bindingElementExtensions>
    </extensions>
    <protocolMapping>
      <add binding="basicHttpsBinding" scheme="http"/>
      <add binding="customBinding" scheme="https"/>
    </protocolMapping>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="TelemetryCorrelationHttpModule"/>
      <add name="TelemetryCorrelationHttpModule" type="Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule, Microsoft.AspNet.TelemetryCorrelation" preCondition="integratedMode,managedHandler"/>
      <remove name="ApplicationInsightsWebTracking"/>
      <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler"/>
    </modules>


    <directoryBrowse enabled="true"/>
    <validation validateIntegratedModeConfiguration="false"/>
  </system.webServer>
</configuration>

我做错了什么或者代码遗漏了什么 任何帮助将不胜感激,因为我以前从未做过 WCF。 顺便说一句,当 WCF 应用程序部署在服务器上时,它使用相同的配置,但如果你想知道为什么我要用服务结构来做它,那不取决于我:)

更新 考虑 LoekD's answer我更新了我的 CreateSoapHTTPSListener 方法,如下所示:

private static ICommunicationListener CreateSoapHTTPSListener(StatelessServiceContext context)
    {
        string host = context.NodeContext.IPAddressOrFQDN;
        var endpointConfig = context.CodePackageActivationContext.GetEndpoint("SecureServiceEndpoint");
        int port = endpointConfig.Port;
        string scheme = endpointConfig.Protocol.ToString();
        var binding = new BasicHttpsBinding(BasicHttpsSecurityMode.Transport);
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
        binding.MaxReceivedMessageSize = 1073741824;

        string uri = ConfigurationManager.AppSettings.Get("ProductManufacturerService");
        Tools.TraceMessage(uri);
        var listener = new WcfCommunicationListener<IProductServiceV20161>(
            serviceContext: context,
            wcfServiceObject: new ProductServiceManufacturer(),
            listenerBinding: binding,
            address: new EndpointAddress(uri)
        );
        listener.ServiceHost.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, ConfigurationManager.AppSettings.Get("ServiceCertificateThumbprint"));
        listener.ServiceHost.Credentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, ConfigurationManager.AppSettings.Get("ClientCertificateThumbprint"));

        // Check to see if the service host already has a ServiceMetadataBehavior
        ServiceMetadataBehavior smb = listener.ServiceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
        // If not, add one
        if (smb == null)
        {
            smb = new ServiceMetadataBehavior();
            smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
            smb.HttpsGetEnabled = true;
            smb.HttpGetEnabled = false;
            smb.HttpsGetUrl = new Uri(uri);
            listener.ServiceHost.Description.Behaviors.Add(smb);
        }
        return listener;
    }

然后我收到一条错误消息:

The Service contains multiple ServiceEndpoints with different ContractDescriptions which each have Name='IProductServiceV20161' and Namespace='namespaceurl/'

我猜这是因为服务端点有两个定义,一个在 app.config 文件中,另一个在 .cs 文件中 我在 app.config 中评论了端点标记并且它起作用了。 但是,与我通过 WCF 应用程序获得的文件相比,我获得的 wsdl 文件缺少一些条目。

更新 2: 如何为服务指定端点身份?是否可以使用自定义 BindingElementExtensionElement 类?

最佳答案

确保服务 list 中的端点声明为“HTTPS”类型,并将 SSL 证书添加到 WCF 服务主机。

你能尝试改变这个吗:

listenerBinding: new BasicHttpsBinding(BasicHttpsSecurityMode.Transport)

进入这个:

listenerBinding: binding

其中绑定(bind)定义为:

var binding = new BasicHttpsBinding(BasicHttpsSecurityMode.Transport)
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;

更多信息 here .

并使用您的 SSL 证书配置服务主机:

listener.ServiceHost.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, "Certificate Thumbprint Here");

关于c# - 带有服务结构的 SOAP - Https 和 Http 绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49512572/

相关文章:

c# - WCF 绑定(bind)中的 <readerQuotas> 是什么?

wcf - 在我的 WCF app.config 中设置 SendTimeout

azure-service-fabric - ASP.Net WebAPI (4.5.2) 找不到 Microsoft.ServiceFabric.Actor

azure - 在调用中将用户和审核信息传递给Service Fabric传输中的可靠服务

eclipse - Azure SF 教程项目使用 gradle 5.4 构建,但不使用 Eclipse 2019-06

c# - 将 TransactionScope 与 Entity Framework 6 结合使用

WCF 使用消息协定序列化枚举

c# - 为什么我不能将 newtonsoft.Json.dll 引用添加到我的项目中?

c# - 为什么包含命名参数会导致 "type arguments for method cannot be inferred from usage"错误?

c# - 无法在 Azure Function 中绑定(bind) BlobProperties