使用自定义主体和WCF服务的身份时出现问题

时间:2011-03-15 10:57:47

标签: multithreading wcf identity principal

我们使用自定义主体和身份类型(ProdigyPrincipal / ProdigyIdentity),因为我们需要在我们的程序和服务中提供额外信息。在程序中,我们设置了主体和身份。与WCF服务通信时,将设置主体和标识,但在转换为我们自己的类型后,主体和标识为空。

我注意到在调试模式和单元测试模式下运行之间存在差异。在调试模式下,主体和标识的类型是 WindowsPrincipal WindowsIdentity 类型。在单元测试模式下,类型是GenericPrincipal和GenericIdenity。在转换为自定义类型的两种情况下,值都为null。

设置和获取主体/身份是通过 Thread.CurrentPrincipal 完成的。 在绑定部分的App.configs中,安全模式设置为“Transport”。

用于设置/获取主体和身份的已用函数:

  protected static bool SetProdigyPrincipal()
  {
     #region require Thread.CurrentPrincipal should not be null

     if (Thread.CurrentPrincipal == null) // OK
     {
        throw new InvalidOperationException("SetProdigyPrincipal(): Thread.CurrentPrincipal should not be null");
     }

     #endregion require Thread.CurrentPrincipal should not be null

     var prodigyPrincipal = Thread.CurrentPrincipal as ProdigyPrincipal;

     #region require prodigyPrincipal should not be null

     if (prodigyPrincipal == null) // NOT OK
     {
        throw new InvalidOperationException("SetProdigyPrincipal(): prodigyPrincipal should not be null");
     }

     #endregion require prodigyPrincipal should not be null

     // Get the Windows identity from the current principal
     var prodigyIdentity = Thread.CurrentPrincipal.Identity as ProdigyIdentity;

     #region require windowsIdentity should not be null

     if (prodigyIdentity == null) // NOT OK
     {
        throw new InvalidOperationException("SetProdigyPrincipal(): prodigyIdentity should not be null");
     }

     #endregion require windowsIdentity should not be null

     // Create new instance of Prodigy principal
     var newProdigyPrincipal = new ProdigyPrincipal(prodigyIdentity);

     #region require prodigyPrincipal should not be null

     if (prodigyPrincipal == null)
     {
        throw new InvalidOperationException("SetProdigyPrincipal(): prodigyPrincipal should not be null");
     }

     #endregion require prodigyPrincipal should not be null

     // Set the prodigy principal
     var principalIsSet = ProdigyPrincipal.SetCurrentPrincipal(newProdigyPrincipal, ProdigyService.EnterpriseServiceBus);

     // Return principal is set status
     return principalIsSet;
  }

有谁知道为什么无法从 Thread 中检索自定义主体和身份类型?

亲切的,汉斯

1 个答案:

答案 0 :(得分:8)

WCF通过 ServiceAuthorizationBehavior 实现了同一目标的更标准方法。

如果将其PrincipalPermissionMode属性设置为“Custom”,则允许您提供自定义IAuthorizationPolicy,您可以通过该自定义IPrincipal为WCF ServiceSecurityContext提供自定义public class DemoAuthorizationPolicy : IAuthorizationPolicy { private readonly string id = Guid.NewGuid().ToString(); public string Id { get { return this.id; } } public ClaimSet Issuer { get { return ClaimSet.System; } } public bool Evaluate(EvaluationContext context, ref object state) { // Here, create your custom principal IIdentity customIdentity = new GenericIdentity("myUserName", "myCustomAuthenticationType"); IPrincipal customPrincipal = new GenericPrincipal(customIdentity, new[] { "user", "powerUser" }); // Set EvaluationContext properties context.Properties["Identities"] = new List<IIdentity> { customIdentity }; context.Properties["Principal"] = customPrincipal; return true; } } 。 DispatchRuntime会将此(您的自定义)IPrincipal分配给Thread.CurrentPrincipal - 这就是您所追求的,对吗?

这是IAuthorizationPolicy实现的示例:

  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceAuthorization principalPermissionMode="Custom" >
            <authorizationPolicies>
              <add policyType="PrincipalPermissionModeDemo.DemoAuthorizationPolicy, YourAssemblyName"/>
            </authorizationPolicies>
          </serviceAuthorization>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

这就是你在Web.config中声明ServiceAuthorizationBehavior的方式:

[PrincipalPermission]

在您的服务中,您可以通过Thread.CurrentPrincipal属性利用声明性安全性,您可以从ServiceSecurityContext.Current.PrimaryIdentity获取自定义 IPrincipal ,并且(或者)您也可以获得来自{{1}}的自定义 IIdentity

希望能解决你的问题!