【问题标题】:WCF Security for Internal & External Clients内部和外部客户端的 WCF 安全性
【发布时间】:2014-01-24 20:00:06
【问题描述】:

我计划发布我的 Web 服务,以便在外部网络上使用它。出现的问题是 Web 管理员不想将此 Web 服务设为外部,但希望我将代理包装在它周围并将代理设为外部。我不喜欢代理部分,因为必须同时维护服务和代理的版本控制。我想知道是否有一种简单的方法可以做到这一点,如果您使用外部网络 (URL) 访问 Web 服务以使用 SSL 并请求身份验证,但如果您在内部网络 (URL) 中使用它而不请求身份验证或 SSL。我尝试在 webconfig 中设置两个端点配置,一个是安全的,一个是不安全的,但问题是当您使用 web 服务时,两个绑定都显示并且客户端可以选择一个或其中一个。如果有人以不同的方式执行此操作或推荐不同的方式,请告诉我,通常我会采用一种方法,要么全部安全,要么全部不安全,但根据网络不同。非常感谢:)

【问题讨论】:

    标签: wcf wcf-binding wcf-security


    【解决方案1】:

    您会很高兴知道 WCF 内置了对您的“代理”的支持。它称为路由服务,在 WCF 4.0 及更高版本中可用。

    您可以将其配置为将某个服务合同的 Internet 调用路由到在您的 Intranet 中运行的 WCF 服务。它甚至可以转换绑定,以便外部客户可以使用可以通过防火墙的 HTTP 绑定调用使用 TCP 绑定的内部服务。

    它只需要知道将哪些合约路由到哪里。因此,当您的合同发生变化时无需更新它...

    请参阅here 了解更多信息。

    已编辑: 以下示例system.serviceModel 节点允许客户端向路由服务添加服务引用。诀窍是让路由服务将自己强加为它要路由到的服务。请参阅serviceActivations 节点。请注意,这消除了拥有 .svc 文件的需要。

    接下来,我们定义了两个端点过滤器,将服务请求重定向到路由服务,并将 mex 端点(暴露元数据)请求重定向到路由服务的 mex 端点。请参阅filters 节点。

    最后,我们明确禁止通过 http 公开路由服务本身的元数据,以强制客户端使用 mex(我们正在路由)进行发现。请参阅serviceBehaviors 节点。

    再次编辑:添加了 mex 大小限制的解决方案

    <system.serviceModel>
      <serviceHostingEnvironment>
        <serviceActivations>
          <!--Lets the routing service impose himself as Service.svc  (No .SVC file is needed!!!) -->
          <add service="System.ServiceModel.Routing.RoutingService" relativeAddress="Service.svc" />
        </serviceActivations>
      </serviceHostingEnvironment>
      <bindings>
        <wsHttpBinding>
          <!-- a mexHttpBinding is in fact a wsHttpBinding with security turned off -->
          <binding name="mexBinding" maxReceivedMessageSize="5000000">
            <security mode="None"/>
          </binding>
        </wsHttpBinding>
      </bindings>
      <behaviors>
        <serviceBehaviors>
          <behavior >
            <!-- Use the filter table with the name 'Filters' defined below -->
            <routing routeOnHeadersOnly="false" filterTableName="Filters"/>
            <serviceDebug includeExceptionDetailInFaults="true"/>
            <!-- Disable exposing metadata for this routing service to force discovery using mex -->
            <serviceMetadata httpGetEnabled="false"/>
          </behavior>
        </serviceBehaviors>
      </behaviors>
      <routing>
        <filters>
          <!-- Declare a routing filter that filters on endpoint Service.svc -->
          <filter name="WcfServiceFilter" filterType="EndpointAddress" filterData="http://localhost/ServiceRouter/Service.svc" />
          <!-- Declare a routing filter that filters on mex endpoint of Service.svc -->
          <filter name="WcfServiceFilter.mex" filterType="EndpointAddress" filterData="http://localhost/ServiceRouter/Service.svc/mex"/>
        </filters>
        <filterTables>
          <!-- Declare the routing table to use -->
          <filterTable name="Filters">
            <!-- requests that match the WcfServiceFilter (declared above) should be routed to the client endpoint WcfService -->
            <add filterName="WcfServiceFilter" endpointName="WcfService"/>
            <!-- requests that match the WcfServiceFilter.mex (declared above) should be routed to the client endpoint WcfService.mex -->
            <add filterName="WcfServiceFilter.mex" endpointName="WcfService.mex"/>
          </filterTable>
        </filterTables>
      </routing>
      <services>
        <!-- Declare our service instance and the endpoints it listens on -->
        <service name="System.ServiceModel.Routing.RoutingService">
          <!-- Declare the endpoints we listen on -->
          <endpoint name="WcfService" contract="System.ServiceModel.Routing.IRequestReplyRouter" binding="wsHttpBinding" />
          <endpoint name="WcfServiceFilter.mex" address="mex" contract="System.ServiceModel.Routing.IRequestReplyRouter" binding="mexHttpBinding" />
        </service>
      </services>
      <client>
        <!-- Define the client endpoint(s) to route messages to -->
        <endpoint name="WcfService" address="http://localhost/WcfService/Service.svc" binding="wsHttpBinding" contract="*" />
        <endpoint name="WcfService.mex" address="http://localhost/WcfService/Service.svc/mex" binding="wsHttpBinding" bindingConfiguration="mexBinding" contract="*" />
      </client>
    </system.serviceModel>
    

    【讨论】:

    • 我已经阅读了路由服务并尝试了一些示例,但看起来它使客户端使用该服务变得复杂,因为您确实无法引用该服务,而是一个不清楚方法的虚拟代理除非您单独指定 wsdl...我理解正确吗?
    • 路由服务是一个透明的代理,所以你的客户不需要知道它的存在。有关如何配置路由服务以公开其背后服务的元数据的更多信息,请参阅this thread中的答案
    • 太棒了...感谢您的帮助,因为这是我第一次创建路由服务...我创建了一个示例服务,并且能够通过“代理”获取服务元数据。现在,当我尝试将“代理”链接到我们的实际服务时,它给了我一个错误。在单步执行代码时,我发现某些 DataContracts 存在问题,这没有任何意义,因为它们没有什么不寻常的地方。如果我删除 DataContract,如果我把它带回来,它就会失败……你以前是怎么经历的?有什么想法吗?
    • 这是错误:下载“localhost/SericeRouter/RouterService.svc/MyService/_vti_bin/…”时出错。请求失败,HTTP 状态为 400:错误请求。元数据包含无法解析的引用:“localhost/SericeRouter/RouterService.svc/MyService”。元数据包含无法解析的引用:“localhost/SericeRouter/RouterService.svc/MyService”。如果在当前解决方案中定义了服务,请尝试构建解决方案并再次添加服务引用。
    • 仅供未来读者参考:经过长时间的交谈,我们破解了 mex 大小限制问题。我更改了上面的示例配置以包含解决方案。
    猜你喜欢
    • 2016-03-29
    • 1970-01-01
    • 1970-01-01
    • 2014-02-04
    • 1970-01-01
    • 2012-07-24
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    相关资源
    最近更新 更多