简体   繁体   English

基于 IIS 绑定将 WCF 端点动态绑定到 HTTPS

[英]Dynamically Bind WCF Endpoints To HTTPS Based on IIS Bindings

I have an WCF service that I am converting from HTTP to HTTPS.我有一个 WCF 服务,我正在将它从 HTTP 转换为 HTTPS。 Clients currently have a hardcoded HTTP URL to this service.客户端当前具有该服务的硬编码 HTTP URL。 The server binds the service using some custom behaviors in the Web.config file:服务器使用 Web.config 文件中的一些自定义行为绑定服务:

  <service behaviorConfiguration="MyServiceBehaviors" name="MyService">
    <endpoint address="" behaviorConfiguration="MyEndpointBehaviors" binding="customBinding" bindingConfiguration="MyHttpCustomBinding" name="MyService" contract="IMyService" />
  </service>

I want to bind the WCF service to HTTP and HTTPS.我想将 WCF 服务绑定到 HTTP 和 HTTPS。 I can do this with two entries in the Web.config file:我可以使用 Web.config 文件中的两个条目执行此操作:

  <service behaviorConfiguration="MyServiceBehaviors" name="MyService">
    <endpoint address="" behaviorConfiguration="MyEndpointBehaviors" binding="customBinding" bindingConfiguration="MyHttpCustomBinding" name="MyService" contract="IMyService" />
    <endpoint address="" behaviorConfiguration="MyEndpointBehaviors" binding="customBinding" bindingConfiguration="MyHttpsCustomBinding" name="MyService" contract="IMyService" />
  </service>

I also have a requirement that the server may not have HTTPS enabled at first.我还要求服务器一开始可能没有启用 HTTPS。 So IIS may not be bound to HTTPS port 443 at the time the WCF service is activated.所以IIS在WCF服务激活时可能没有绑定HTTPS端口443。

If IIS is not bound to HTTPS, and the Web.config binds to both endpoints like the above example, and a client tries to activate the service on the HTTP endpoint, the service fails to start with the following activation exception:如果 IIS绑定到 HTTPS,并且 Web.config 像上面的示例一样绑定到两个终结点,并且客户端尝试在 HTTP 终结点上激活该服务,则该服务将无法启动并出现以下激活异常:

WebHost failed to process a request. WebHost 无法处理请求。 Sender Information: System.ServiceModel.ServiceHostingEnvironment+HostingManager/45653674 Exception: System.ServiceModel.ServiceActivationException: The service '/MyApp/MyService.svc' cannot be activated due to an exception during compilation.发件人信息:System.ServiceModel.ServiceHostingEnvironment+HostingManager/45653674 异常:System.ServiceModel.ServiceActivationException:由于编译期间出现异常,无法激活服务“/MyApp/MyService.svc”。 The exception message is: Could not find a base address that matches scheme https for the endpoint with binding CustomBinding.异常消息是:找不到与具有绑定 CustomBinding 的端点的方案 https 匹配的基地址。 Registered base address schemes are [http].注册的基地址方案是 [http]。

I think the WCF service needs to bind to HTTPS only when HTTPS is enabled in IIS.我认为只有在 IIS 中启用 HTTPS 时,WCF 服务才需要绑定到 HTTPS。 I don't see a way to accomplish this in the Web.config file, so I assume I will need to do some dynamic server binding.我在 Web.config 文件中看不到实现此目的的方法,因此我假设我需要进行一些动态服务器绑定。

How can I selectively bind the HTTP and HTTPS endpoints in WCF based on IIS configuration?如何根据 IIS 配置有选择地绑定 WCF 中的 HTTP 和 HTTPS 端点?

I also don't see a way the service could be notified if the IIS binding changes to add/remove HTTPS, but I am OK with asking admins to recycle the application pool/IISRESET/reboot to get the service to use the updated settings.如果 IIS 绑定更改为添加/删除 HTTPS,我也没有看到可以通知服务的方式,但我可以要求管理员回收应用程序池/IISRESET/重启以使服务使用更新的设置。

I was able to get this to work with the following steps:我能够通过以下步骤使其工作:

Add a Factory attribute to the MyService.svc file that will be able to construct the service:将 Factory 属性添加到 MyService.svc 文件中,以便能够构建服务:

<%@ ServiceHost Language="C#" Debug="true"
    Service="MyService"
    Factory="MyServiceFactory" %>

Create the factory class in the WCF service DLL:在 WCF 服务 DLL 中创建工厂类:

public class MyServiceFactory : ServiceHostFactory
{
    public override ServiceHostBase CreateServiceHost(string service, Uri[] baseAddresses)
    {
        return CreateServiceHost(typeof(MyService), baseAddresses);
    }

    protected override ServiceHost CreateServiceHost(Type t, Uri[] baseAddresses)
    {
        var serviceHost = new ServiceHost(t, baseAddresses);
        foreach (Uri address in baseAddresses)
        {
            bool secure = false;
            if (address.Scheme == "https")
                secure = true;

            var binding = GetMyCustomBinding(secure);
            var endpoint = serviceHost.AddServiceEndpoint(typeof(IMyService), binding, address);

            endpoint.Behaviors.Add(new MyEndpointBehavior());
        }

        return serviceHost;
    }
}

The given array of baseAddresses include the endpoint Uris to which IIS is bound.给定的 baseAddresses 数组包括绑定 IIS 的端点 Uris。 For each endpoint, bind the service to the endpoint using a custom binding.对于每个端点,使用自定义绑定将服务绑定到端点。 If the endpoint is "https", then use a secure binding;如果端点是“https”,则使用安全绑定; otherwise, use a standard binding.否则,使用标准绑定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM