HttpContext 在以 ASP.NET 兼容模式运行的 WCF 服务中为空

Posted

技术标签:

【中文标题】HttpContext 在以 ASP.NET 兼容模式运行的 WCF 服务中为空【英文标题】:HttpContext is null in WCF service running in ASP.NET Compatibility Mode 【发布时间】:2011-05-03 12:06:01 【问题描述】:

我有一个托管 WCF 服务的 asp.net 网站。然后从桌面应用程序访问此服务。在我的服务中,在执行 UserNamePasswordValidator 类的 Validate 方法期间,HttpContext 始终为空。我使用用户名作为客户端凭据类型。我需要访问 http 上下文以获取访问服务的 Url,以便正确验证用户名和密码,因为可以使用不同的 Url 访问该站点,并且每个 URL 都有不同的用户存储。

包含将在验证器类(以及验证器类)之后调用的方法的类的以下属性

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]

我有一个服务配置如下:

<system.serviceModel>
  <bindings>
    <wsHttpBinding>
      <binding name="wsHttpSecurityOptions">
        <security mode="Message">
          <message clientCredentialType="UserName" establishSecurityContext="true" negotiateServiceCredential="true"/>
          <transport clientCredentialType="Certificate" proxyCredentialType="None"/>
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
  <behaviors>
    <serviceBehaviors>
    <behavior name="SecurityServiceBehavior">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="true"/>
      <serviceCredentials>
        <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WCFServer.MyAuthenticator" includeWindowsGroups="false"/>
        <serviceCertificate findValue="myurl.com" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/>
      </serviceCredentials>
    </behavior>
    </serviceBehaviors>
  </behaviors>
  <services>
    <service behaviorConfiguration="SecurityServiceBehavior" name="Test.WCF.Actions">
      <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpSecurityOptions" contract="WCFServer.IActions"/>
    </service>
  </services>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>

我见过HttpContext is not initialised on first call bug,但每次调用服务都会发生这种情况,即使我在同一个连接上多次调用同一个方法

编辑:澄清问题以回答 marc_s 的评论和 Aliostad 的问题

编辑:添加了以下链接,建议 http 上下文不应为空

http://blogs.msdn.com/b/wenlong/archive/2006/01/23/516041.aspx http://msdn.microsoft.com/en-us/library/aa702682(v=VS.90).aspx

有人可以帮我解决这个问题吗?我宁愿不必将网站的 Url 放在我所有网站的 appSettings 配置部分。

【问题讨论】:

在您的 Validate 方法中,您需要 HttpContext 做什么?? 它是在 UserNamePasswordValidator.Validate 中还是在您的 [OperationContract] 方法中为空?我不确定从验证器访问 HttpContext 是否受支持... 仅在 UserNamePasswordValidator.Validate 方法中为空。当传输安全性默认为 Windows 时,我在早期的开发版本中使用了此功能(绝对是用户名消息安全性)。 ServiceOperation.Current 在这个阶段应该是空的,但我找不到任何可以确认 HttpContext 也将为空的东西。 【参考方案1】:

问题是您想从 Validate 方法访问 HttpContext。据我了解,内部 WCF 实现 Validate 方法在不同的线程中运行。按照设计,该线程无法访问任何可用于处理请求的主线程的上下文。在 Validate 方法中,您无法访问任何基于 WCF 的上下文(OperationContext、ServiceSecurityContext 等),所以我认为它与 HttpContext 相同。

【讨论】:

感谢您的回答,但它不能解决我(仍然)遇到的问题,而且我标记的解决方案(如所指出的那样)确实存在安全问题。 不,它不能解决问题。答案的重点是 WCF 的密码验证根本不应该在您的场景中使用。与其尝试破解 WCF 的实现,不如简单地创建自己的完全独立的实现。 @LadislavMrnka 但是有没有办法将身份验证数据传递给服务方法?例如。角色,我在身份验证方法中添加。【参考方案2】:

UserNamePasswordValidator 的 validate 方法在 asp.net 管道初始化之前执行。所以 HttpContext 为空。尝试改用 OperationContext。

【讨论】:

OperationContext 肯定只在 validate 方法执行后创建。希望我能抽出一些时间来挖掘 HttpContext 在 validate 方法中工作的代码,以提供一个示例。【参考方案3】:

我不清楚您要做什么。

aspNetCompatibilityEnabled 仅在您使用不需要绑定配置的新 WCF REST API 时才有意义 - 据我所知。 WCF REST 中的绑定由 ASP.NET MVC 路由管理。

如果您使用配置 API 设置经典绑定,那么您没有使用新功能,因此“no aspNetCompatibilityEnabled for you”!

【讨论】:

我正在尝试从我的 WCF 服务访问 HttpContext,如“在 ASP.NET 兼容模式下托管 WCF 服务”部分中的 msdn.microsoft.com/en-us/library/aa702682.aspx 所示。当您在 asp.net 网站(WebForms 和 MVC)中嵌入 WCF 端点时,aspNetCompatibilityEnabled 非常有意义【参考方案4】:

所以最后我想到了一个解决方法。我通过用户名参数将服务正在运行的 url 传递给 UserNamePasswordValidator.Validate。我使用 $username$|$siteurl$ 格式。然后在服务器上我将两者分开。需要注意的一件事是

ServiceSecurityContext.Current.PrimaryIdentity.Name
属性将包含 $username$|$siteurl$ 用于请求的其余部分,因此您必须在每次要访问它时将其拆分为其组件。

只是为了澄清我为什么需要这样做。我们的系统可以在同一个主目录上运行具有不同 url 的多个站点,每个站点都有与 url 相关联的单独身份验证。因此,如果没有 url,我将无法验证请求。我一直在使用 appSetting 键来提供 url,但这意味着每个站点都必须有自己的主目录。

【讨论】:

如果我理解正确,您正在使用客户端提供的信息来确定使用哪个用户存储进行身份验证。从安全角度来看,这非常非常糟糕,因为我可以使用服务 B 的凭据轻松访问服务 A @csauve - 是的,这并不理想,这是一种妥协。如果您为该服务构建了自己的客户端,则可以选择不同的用户存储来尝试使用您的凭据。我这样做是因为我看不到其他方法(除了重建用户身份验证系统)来完成这项工作。为了减少有人为服务构建自己的客户端的机会,我已将 httpGetEnabled 设置为安全服务的错误。如果您有更好的答案/解决方法,我愿意接受。

以上是关于HttpContext 在以 ASP.NET 兼容模式运行的 WCF 服务中为空的主要内容,如果未能解决你的问题,请参考以下文章

在 ASP.NET Core 中访问当前的 HttpContext

ASP.NET HttpContext 在 Azure 上为空

ASP.NET Core 2.0中的HttpContext

我们可以扩展 HttpContext.User.Identity 以在 asp.net 中存储更多数据吗?

Asp.net中的Cache--HttpRuntim.Cache 和 HttpContext.Current.Cache

如何在 ASP.NET Core 中获取 HttpContext.Current? [复制]