【问题标题】:Problem using custom principal and identity with WCF services将自定义主体和身份与 WCF 服务一起使用时出现问题
【发布时间】:2011-03-15 10:57:46
【问题描述】:

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

我注意到在调试模式和单元测试模式下运行是有区别的。在调试模式下,主体和身份的类型是 WindowsPrincipalWindowsIdentity 类型。在单元测试模式下,类型是 GenericPrincipal 和 GenericIdenity。在这两种情况下,当转换为自定义类型时,值都是 null。

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

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

  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 中检索到自定义主体和身份类型?

亲切的问候,汉斯

【问题讨论】:

    标签: multithreading wcf identity principal


    【解决方案1】:

    WCF 通过ServiceAuthorizationBehavior 有一种更标准的方式来实现相同的目标。

    如果您将其 PrincipalPermissionMode 属性设置为“自定义”,它允许您提供自定义 IAuthorizationPolicy,通过它您可以使自定义 IPrincipal 可用于 WCF ServiceSecurityContext。 DispatchRuntime 会将这个(您的自定义)IPrincipal 分配给 Thread.CurrentPrincipal - 这就是您所追求的,对吧?

    这是一个示例 IAuthorizationPolicy 实现:

    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;
        }
    }
    

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

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

    在您的服务中,您可以通过[PrincipalPermission] 属性利用声明性安全性,您可以从Thread.CurrentPrincipal 获取自定义IPrincipal,并且(或者)您还可以获取自定义来自ServiceSecurityContext.Current.PrimaryIdentity的身份

    希望能解决您的问题!

    【讨论】:

    • 好电话 - 我知道 context.Properties["Principal"] 是设置 Thread.CurrentPrincipal 的机制,但直到我在 EvaluationContext 上使用 DotPeek,我才知道 context.Properties[ "Identities"] 是设置 ServiceSecurityContext.Current.PrimaryIdentity 的快捷方式...如果我可以扔掉 WCF,我会....
    猜你喜欢
    • 2011-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-03
    • 2023-01-03
    • 2011-08-26
    • 2017-03-28
    • 1970-01-01
    相关资源
    最近更新 更多