ASP.Net WCF 服务的 Thread.CurrentPrincipal 被联合 (WIF) 环境中的某些拦截器丢弃
-
20-09-2019 - |
题
我有一个托管在 IIS (.svc) 中的每次调用 WCF 服务。在服务的构造函数中,我设置了 Thread.CurrentPrincipal = HttpContext.Current.User 按照 本文. 。在这种情况下 HttpContext.Current.User 属于类型 Microsoft.IdentityModel.Claims.ClaimsPrincipal 并具有从我的自定义被动 STS 发回的声明。
然而,一旦我踏入我的服务运营并检查 Thread.CurrentPrincipal, ,而这个对象仍然是类型 Microsoft.IdentityModel.Claims.ClaimsIdentity, ,对象本身不再与 HttpContext.Current.User (Thread.CurrentPrincipal.Identity 上的 IsAuthenticated = false、AuthenticationType = "" 且名称为 null),而这些值仍然全部正确填写 HttpContext.Current.User. 。这告诉我,某些东西正在拦截对操作的调用,并错误地将当前主体更改为某些通用的、空的、未经身份验证的声明主体。
我检查了构造函数和操作中的线程 ID,它在两个地方都是相同的,并评估 Thread.CurrentPrincipal 在分配自后的立即窗口中 HttpContext.Current.User 显示在构造函数中正确设置了线程标识,因此肯定在构造函数和方法之间执行了某些操作,并且某些操作正在改变我的 Thread.CurrentPrincipal.
有人知道这是怎么回事吗?我该如何防止/修复这种行为?
解决方案 2
当为 WIF 联合配置服务时,您可以调用
FederatedServiceCredentials.ConfigureServiceHost(this);
此调用的部分作用是设置一个自定义 服务授权管理器 类型的 身份模型服务授权管理器 在服务主机上。该授权管理器似乎在实例的激活(构造)和操作的执行之间被调用,并且它覆盖 Thread.CurrentPrincipal 与一个实例 IC索赔委托人, ,但它似乎没有意识到它正在 ASP.NET 兼容模式下运行,因此它不会从中提取主体 HttpContext.Current.User.
我能够通过派生来绕过这种行为 身份模型服务授权管理器 并覆盖 检查访问 方法如下:
public class CustomAuthorizationManager : IdentityModelServiceAuthorizationManager
{
public override bool CheckAccess(System.ServiceModel.OperationContext operationContext, ref System.ServiceModel.Channels.Message message)
{
var result = base.CheckAccess(operationContext, ref message);
var properties = operationContext.ServiceSecurityContext.AuthorizationContext.Properties;
properties["Principal"] = System.Web.HttpContext.Current.User;
return result;
}
}
然后将其应用到服务主机,如下所示:
protected override void InitializeRuntime()
{
FederatedServiceCredentials.ConfigureServiceHost(this);
this.Authorization.ServiceAuthorizationManager = new CustomAuthorizationManager();
base.InitializeRuntime();
}
现在当我进入我的服务操作时,我有正确的 IC索赔委托人 在 Thread.CurrentPrincipal, ,如此声明式 校长许可 现在按预期工作。
其他提示
我刚刚遇到了类似的问题。我在 WCF 服务的构造函数中设置了自定义主体。当我离开构造函数并进入我调用的方法时,thread.currentprincipal 被空的覆盖。我通过添加以下行为解决了这个问题:
<serviceAuthorization principalPermissionMode="None"></serviceAuthorization>
这对我来说效果很好。
呼叫的配置设置 FederatedServiceCredentials.ConfigureServiceHost(这);
如下所示 在 system.serviceModel 中添加以下内容
<extensions>
<behaviorExtensions>
<add name="federatedServiceHostConfiguration" type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</behaviorExtensions>
</extensions>
在里面添加以下行
<behavior name="serviceBehavior">
<federatedServiceHostConfiguration name="MyService" />
我的猜测是没有任何东西拦截呼叫。CurrentPrincipal 要么在您检查时重置,要么您处于不同的线程中。
分配给 CurrentPrincipal 后立即检查它,您应该看到正确的值。