asp.net – Thread.CurrentPrincipal在使用WebGet调用的WCF服务中未设置

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

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

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

和约束力

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

当服务被调用时,Thread.CurrentPrincipal被设置为一个RolePrincipal,客户端的Windows身份和角色由配置的提供者提供.

一切都与世界很好.

现在,我已经添加了一些额外的WCF服务,这些服务是由svc文件中的REST-Ajax调用消耗的:Factory =“System.ServiceModel.Activation.WebScriptServiceHostFactory”,服务合同中的WebGet属性和AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode).允许)属性在服务实现.

我也在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服务一样?

UPDATE
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. Aaargh.

我已经看到了implement a custom IAuthorizationPolicy的建议,并会研究如果我没有找到更好的解决方案,但为什么我需要实现一个自定义策略来利用现有的ASP.NET授权功能?如果我有principalPermissionMode =“UseAspNetRoles”,肯定WCF应该知道我想要什么?

解决方法

这是个有趣的问题.我没有和你一样的设置,所以很难测试我的建议是否会适用于你的用例,但是我可以分享一些类似的项目为我们工作的东西.

我们如何保持Thread.CurrentPrincipal和HttpContext.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.User和Thread.CurrentPrincipal;但是,以上是你要求的.

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

对于集成应用程序池:

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

对于旧的经典应用程序池,您必须将其放在< system.web>< httpModules>< / httpModules>< /system.web\u0026gt; 您可能需要播放AuthenticationRequest事件处理程序和/或注册处理程序的顺序.因为我们完全是自定义的,它可能与你所需要的不一样.我们实际上抓住了Forms Authentication cookie,解密它等等…你可能需要ping一些内置的WindowsAuthentication方法. 我相信这是处理您的应用程序身份验证的更通用的方法,因为它适用于所有HttpRequests,无论是页面请求,IHttpHandler,某些第三方组件等…这将保持在您的应用程序中一致.

相关文章

这篇文章主要讲解了“WPF如何实现带筛选功能的DataGrid”,文...
本篇内容介绍了“基于WPF如何实现3D画廊动画效果”的有关知识...
Some samples are below for ASP.Net web form controls:(fr...
问题描述: 对于未定义为 System.String 的列,唯一有效的值...
最近用到了CalendarExtender,结果不知道为什么发生了错位,...
ASP.NET 2.0 page lifecyle ASP.NET 2.0 event sequence cha...