我使用端点行为配置此服务:
<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,某些第三方组件等…这将保持在您的应用程序中一致.