【问题标题】:Thread.CurrentPrincipal is not set in WCF service called using WebGetThread.CurrentPrincipal 未在使用 WebGet 调用的 WCF 服务中设置
【发布时间】:2012-01-27 07:21:17
【问题描述】:

我有一个托管在 IIS 中的网站,它使用 Windows 身份验证并公开 WCF Web 服务。

我使用端点行为配置此服务:

<serviceAuthorization principalPermissionMode ="UseAspNetRoles" 
                   roleProviderName="MyRoleProvider"/>

还有一个绑定:

 <security mode="TransportCredentialOnly">
    <transport clientCredentialType="Ntlm" />
 </security>

调用服务时,Thread.CurrentPrincipal 设置为 RolePrincipal,客户端的 Windows 身份和角色由配置的提供程序提供。

这个世界一切都好。

现在我添加了一些由 REST-ful Ajax 调用使用的额外 WCF 服务:svc 文件中的Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"、服务协定中的WebGet 属性和服务实现中的AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed) 属性。

我还按照 MSDN 中的建议将以下咒语添加到 web.config:

<system.serviceModel>
    ...
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
    ...
</system.serviceModel>

我的 Ajax 服务几乎按我想要的方式工作。当它被调用时,HttpContext.Current.User 被设置为 RolePrincipal,具有我期望的角色。但是Thread.CurrentPrincipal 仍然设置为未经身份验证的GenericPrincipal

所以我需要在我的每个服务方法中添加一行代码:

Thread.CurrentPrincipal = HttpContext.Current.User

配置文件中是否有任何咒语可用于让Thread.CurrentPrincipal 自动设置,就像普通的 SOAP 服务一样?

更新 Here's 来自有同样问题的人的博客,并通过实现自定义行为解决了它。肯定有开箱即用的方法吗?

更新 2 回来为此添加赏金,因为它在一个新项目中再次困扰我,在 .NET 3.5 上使用支持 WCF WebGet 的服务。

我尝试了许多选项,包括设置 principalPermissionMode="None",但没有任何效果。以下是发生的事情:

  • 我导航到调用我的服务的 WebGet URL:http://myserver/MyService.svc/...

  • 我在 Global.asax“Application_AuthorizeRequest”中设置了一个断点。命中此断点时,“HttpContext.Current.User”和“Thread.CurrentPrincipal”都已设置为使用我配置的 ASP.NET RoleProvider 的“RolePrincipal”。这是我想要的行为。

  • 当我的服务的 OperationContract 方法被调用时,我有第二个断点。命中此断点时,HttpContext.Current.User 仍然引用我的 RolePrincipal,但 Thread.CurrentPrincipal 已更改为 GenericPrincipal。啊。

我已经看到implement a custom IAuthorizationPolicy 的建议,如果我没有找到更好的解决方案,我会考虑这个问题,但是为什么我需要实施自定义策略来利用现有的 ASP.NET 授权功能?如果我有 principalPermissionMode = "UseAspNetRoles",WCF 应该知道我想要什么吗?

【问题讨论】:

  • 你遇到过这个吗? (从模糊的描述中,我实际上无法判断这是一个或多或少复杂的解决方案。)social.msdn.microsoft.com/Forums/en/wcf/thread/…
  • @mootinator,不,情况不一样。我正在使用 RoleProvider 并且 HttpContext.Current.User 设置正确。但不是 Thread.CurrentPrincipal。
  • 我想知道这是否是他们在 .NET 4.5 或 4.5.1 中修复的错误。您是否尝试过针对最新的 .NET 版本?
  • @Noseratio - 好点,但我对 4.5 也有同样的问题

标签: asp.net .net ajax wcf


【解决方案1】:

这是一个有趣的问题。我的设置与您不同,因此很难测试我的建议是否完全适用于您的用例,但我可以与类似项目分享对我们有用的方法。

我们如何保持 Thread.CurrentPrincipalHttpContext.Current.User 同步

我们编写了一个名为“AuthenticationModule”的HttpModule,它继承自IHtppModule

然后我们附加到在请求生命周期的早期发生的 HttpApplication.AuthenticateRequest 事件。

在我们的 AuthenticateRequest 事件处理程序中,我们实现了应用程序的特定要求,包括设置 Thread.CurrentPrincipal 以及在必要时设置当前上下文用户。这样,您只需为整个应用程序实现此代码一次,如果它发生更改(例如,如果您实现自定义 Principal IIDentity),您只有一个地方可以更改它。 (不要在每个服务方法中重复此代码。)

public class AuthenticationModule : IHttpModule
{
    public void Dispose() { return; }

    public void Init(HttpApplication app)
    {
        app.AuthenticateRequest += new EventHandler(app_AuthenticateRequest);
    }

    void app_AuthenticateRequest(object sender, EventArgs e)
    {
        HttpApplication app = (HttpApplication)sender;

        // This is what you were asking for, but hey you 
        // could change this behavior easily.
        Thread.CurrentPrincipal = app.Context.User;
    }
}

我们的实际上有点复杂,因为我们实现了一个自定义的IIdentity,创建了一个GenericPrincipal 的实例,然后将它分配给app.Context.UserThread.CurrentPrincipal;但是,以上是您所要求的。

不要忘记在web.config 中注册新的 HttpModule!

对于集成应用程序池:

<system.webServer>
    <modules>
      <add name="AuthenticationModule" type="YourNameSpace.AuthenticationModule" preCondition="integratedMode" />
    </modules>
</system.webServer>

对于旧的经典应用程序池,您必须将其放入 &lt;system.web&gt;&lt;httpModules&gt;&lt;/httpModules&gt;&lt;/system.web&gt;

您可能需要使用 AuthenticationRequest 事件处理程序内部的内容和/或注册处理程序的顺序。因为我们是完全定制的,所以它可能与您需要的不同。我们实际上抓取了 Forms Authentication cookie,对其进行解密等……您可能需要 ping 一些 WindowsAuthentication 的内置方法。

我相信这是一种更通用的方法来处理您的应用程序身份验证内容,因为它适用于所有HttpRequests,无论是页面请求、IHttpHandler、某些第 3 方组件等...这将保留它在整个应用中保持一致。

【讨论】:

  • 感谢您的回复。我知道有办法通过编码来实现我想要的;例如我在问题中链接的博客中描述的自定义行为。但我真正在寻找的是一种仅通过配置来实现这一目标的方法 - 或者解释为什么这是不可能的权威来源。
【解决方案2】:

我不确定。也许这会有所帮助

<configuration>
  <system.web>
    <identity impersonate="true" />
  </system.web>
</configuration>

http://msdn.microsoft.com/en-us/library/134ec8tc(v=vs.80).aspx

【讨论】:

    猜你喜欢
    • 2021-03-25
    • 1970-01-01
    • 2015-11-16
    • 1970-01-01
    • 2010-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-29
    相关资源
    最近更新 更多