WCF 服务中的无意模拟

Posted

技术标签:

【中文标题】WCF 服务中的无意模拟【英文标题】:Unintentional impersonation in WCF service 【发布时间】:2012-11-02 15:46:00 【问题描述】:

(注意:我终于自己解决了这个问题,模拟结果并不是主要问题;但是,如果有人知道为什么会发生模拟,请告诉我。)

我们有一个从 Silverlight 应用程序调用的 WCF 服务(它们由同一个 Web 应用程序托管)。与操作本身花费的时间相比,调用服务的速度非常慢。 WCF 跟踪日志使它看起来花费了超过两秒钟的时间来模拟(参见第五行):

[15:32:3.193] From: Processing message 1.
[15:32:3.193] Activity boundary.
[15:32:3.193] Received a message over a channel.
[15:32:3.194] ServiceChannel information.
[15:32:5.539] Security Impersonation succeeded at the server.
[15:32:5.540] To: Execute 'MyNamespace.GetFloorplan'.
[15:32:5.540] Activity boundary.
[15:32:6.302] From: Execute 'MyNamespace.GetFloorplan'.
[15:32:6.302] Activity boundary.
[15:32:6.305] Sent a message over a channel.
[15:32:6.306] Activity boundary.

这让我感到困惑,因为我认为模拟是您需要在配置中显式启用(或从代码触发)的东西。我刚作为顾问加入这个项目,所以我还没有对整个源代码的完整概述,但是源代码中的任何地方都不存在“模拟”或“模拟”文本。更令人困惑的是,服务内部的System.Threading.Thread.CurrentPrincipal.Identity 返回一个没有名称的未经身份验证的身份,而System.Security.Principal.WindowsIdentity.GetCurrent().Name 返回IIS APPPOOL\MyCustomAppPool,因此模拟似乎并没有真正完成任何事情。

我们使用表单身份验证和 ASP.NET 兼容模式。当我禁用后者时(我不确定我是否可以永久执行此操作,因为可能有一些我还不知道的依赖于它的功能),Security Impersonation succeeded at the server 从日志中消失,但 @ 之间的时间差987654326@ 和To: Execute 'MyNamespace.GetFloorplan'. 仍然快两秒。在操作中添加[OperationBehavior(Impersonation = ImpersonationOption.NotAllowed)] 没有帮助。

有人了解这里发生了什么吗? (我的目标是摆脱假冒或任何占用这两秒额外时间的东西。)


我们在服务类上有以下属性(我知道理想情况下它们应该在界面上,但我还没有发现它们首先被放置在服务上的原因):

[ServiceContract(Namespace = "")]
[SilverlightFaultBehavior]
[AspNetCompatibilityRequirements(RequirementsMode = 
                                 AspNetCompatibilityRequirementsMode.Allowed)]

这是我们的服务配置:

<system.serviceModel>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" 
                             multipleSiteBindingsEnabled="true" />
  <behaviors>
    <serviceBehaviors>
      <behavior name="">
        <serviceMetadata httpGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="false" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <bindings>
    <customBinding>
      <binding name="SilverlightServiceBinding">
        <binaryMessageEncoding />
        <httpTransport />
      </binding>
    </customBinding>
  </bindings>
  <services>
    <service name="MyNamespace.FloorplanService">
      <endpoint address="" binding="customBinding" 
                bindingConfiguration="SilverlightServiceBinding" 
                contract="MyNamespace.FloorplanService" />
      <endpoint address="mex" binding="mexHttpBinding" 
                contract="IMetadataExchange" />
    </service>
  </services>
</system.serviceModel>

还有我们的客户端配置:

<system.serviceModel>
  <bindings>
    <basicHttpBinding>
      <binding name="BasicHttpBinding_FloorplanService" 
               maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
        <security mode="None" />
      </binding>
    </basicHttpBinding>
  </bindings>
  <client>
    <endpoint address="../Floorplan/FloorplanService.svc"
              binding="basicHttpBinding" 
              bindingConfiguration="BasicHttpBinding_FloorplanService"
              contract="FloorplanServiceProxy.FloorplanService" 
              name="BasicHttpBinding_FloorplanService" />
  </client>
</system.serviceModel>

【问题讨论】:

【参考方案1】:

事实证明,模拟消息是一条红鲱鱼(我应该明白这一点,因为它在禁用 ASP.NET 兼容模式时消失了,而请求仍然花费了几乎同样多的时间)。但是,WCF 跟踪日志确实为我指明了正确的方向:在实际调用操作之前,WCF 中显然发生了非常耗时的事情。最终,我们发现 Web 应用程序包含一个用户身份验证/授权类,由于配置不正确的依赖注入容器,每个请求都会多次调用该类,从而导致许多不必要的数据库请求。

经验教训(以防其他人遇到同样的问题):根据您的配置,WCF 可能会在您的代码执行之前调用身份验证和授权机制,这些可能会占用不可忽略的时间。

【讨论】:

【参考方案2】:

这可能是您网站的 IIS 身份验证设置。

如果您启用了多个身份验证类型,并且它首先尝试其他身份验证类型之一。

【讨论】:

有趣的建议;但是,Web 应用程序只启用了表单身份验证和匿名身份验证(我们需要表单身份验证来验证登录用户是否可以访问请求的资源)。

以上是关于WCF 服务中的无意模拟的主要内容,如果未能解决你的问题,请参考以下文章

WCF 服务中的模拟和传播到 COM 对象

自托管 WCF 中的模拟?

在声明身份验证的 SharePoint 2010 中托管的 WCF 服务中的模拟

在模拟上下文之外调用 WCF 服务?

在 WCF 服务中使用模拟时 SQL 登录失败

WCF 模拟和 SQL 可信连接?