如何在防火墙后面设置安全的WCF服务?

时间:2009-02-12 05:52:59

标签: c# web-services iis wcf

我有一个WCF服务,它位于企业级防火墙后面,它同时进行主机名和端口转换,例如:

https://ws.address.com/Service.svc - > https://serv.internal.com:44000/Service.svc

该服务受SSL-128保护,需要客户端证书。

由于无法从防火墙外部访问内部服务器名称,因此我们必须实现ServiceHostFactory来转换WCF生成的WSDL和XSD导入引用:

public class MyCustomFactory : ServiceHostFactory
    {
        protected override ServiceHost CreateServiceHost(
            Type serviceType, Uri[] baseAddresses)
        {
            MyCustomHost customServiceHost = 
                new MyCustomHost(serviceType, baseAddresses);

            return customServiceHost;
        }

        class MyCustomHost : ServiceHost
        {
            public MyCustomHost(Type serviceType, 
                params Uri[] baseAddresses)
                : base(serviceType, 
                    GetBaseAddresses(serviceType, baseAddresses))
            {                
            }

            protected override void ApplyConfiguration()
            {
                base.ApplyConfiguration();
            }

            private static Uri[] GetBaseAddresses(
                Type serviceType, params Uri[] baseAddresses)
            {
                UriBuilder newBaseAddress = new UriBuilder();
                newBaseAddress.Path = "/" + serviceType.ToString() + 
                    ".svc";

                // from config
                newBaseAddress.Host = 
                    MyCustomSettings.ServiceBaseAddress; 

                if (baseAddresses.Length > 0)
                {
                    newBaseAddress.Scheme = baseAddresses[0].Scheme;
                }

                return new Uri[] { newBaseAddress.Uri };
            }
        }
    }

以下是此问题:除非服务托管在默认SSL端口443上的内部计算机上,否则会收到错误:

没有协议绑定与给定地址“https://ws.address.com/Service.svc”匹配。协议绑定在IIS或WAS配置中的站点级别配置。

从修修补补看,如果我们将内部服务器更改为在443上托管服务,或者将防火墙配置为从44000转发到44000,则一切正常。但是,这些不是我们生产环境中的选择。

编辑: 忘记提及,我们尝试使用IWsdlExportExtension来展平WSDL,但这导致了svcutil或VS2008中代理代码生成的严重问题,所以我们取消了这个想法。

有没有人知道这方面的任何方式?我把头发拉出来了!

提前致谢!

5 个答案:

答案 0 :(得分:1)

您可能需要显式创建自己的Binding(即ServiceModel.WSHttpBinding)并使用该绑定添加服务端点(.AddServiceEndpoint(..))。

http://msdn.microsoft.com/en-us/library/system.servicemodel.servicehost.addserviceendpoint(VS.85).aspx

答案 1 :(得分:0)

您是否尝试过将IP端口放在地址中(从问题看起来不像每次都使用的那样):

https://ws.address.com:44000/Service.svc

另一件事是,WCF在该端口上侦听https流量,请参阅:

http://msdn.microsoft.com/en-us/library/ms733768.aspx

答案 2 :(得分:0)

您不应该更改工厂中的基地址。编写扩展来修改WSDL。这将是一个“IWsdlExportExtension”,您想要覆盖ExportEndpoint来修改端点地址。这将使您的服务听取正确的基地址。

OR

如果您不想开始使用WSDL扩展程序...将现有代码移动到“CreateServiceHost”方法并刮开自定义主机!这不是很好,但应该有用。

答案 3 :(得分:0)

你没有提到你的主人。 IIS / WAS?如果是这样,您可能需要将外部主机名添加到IIS配置到安全绑定列表。

here is some information on changing the host-name in IIS hosted service

这是命令行:

cscript //nologo %systemdrive%\inetpub\adminscripts\adsutil.vbs 
set W3SVC/1/SecureBindings  "10.(internal addr).1:443:ws.address.com"
"127.0.0.1:443:Internal Host name"

如果不解决它,我会选择“routeNpingme”并建议您只需要使用指定https端口和名称的绑定正确指定端点。我认为您可以使用现有的绑定选项执行此操作...但您可能需要创建自定义。

答案 4 :(得分:0)

我的猜测是,在IIS中托管服务的网站的网站绑定配置为仅侦听主机名 serv.internal.com ,而不是外部名称 ws.address。 COM

如果使用主机名配置IIS站点绑定,则会针对所有传入URL检查该主机名。该绑定只能处理具有匹配主机名的URL。

防火墙会将请求重定向到内部服务器,但不会更改传入的URL字符串...