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

发布于 2024-10-22 04:22:07 字数 2292 浏览 1 评论 0原文

我们正在使用自定义主体和身份类型 (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检索自定义主体和身份类型?

亲切的问候,汉斯

We are using a custom principal and identity type (ProdigyPrincipal/ProdigyIdentity) because we need extra information within our programs and services. In the program we set the principal and identity. When communicating with a WCF service the principal and identity are set, but after casting to our own type the principal and identity are null.

I noticed that there is a difference between running in Debug mode and Unit Test mode. In Debug mode the type of the principal and identity are of type WindowsPrincipal and WindowsIdentity. In Unit Test mode the types are GenericPrincipal and GenericIdenity. In both situations when casting to the custom type the value is null.

Setting and getting of the principal/identity is done through Thread.CurrentPrincipal.
In the App.configs in the binding section the security mode is set to 'Transport‘.

Used function for settings/getting the principal and identity:

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

Does anyone know why the custom principal and identity type can not be retrieved from Thread?

Kind regard, Hans

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

暮光沉寂 2024-10-29 04:22:07

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] 属性利用声明性安全性,您可以获得自定义 < em>IPrincipal 来自 Thread.CurrentPrincipal,并且(或者)您还可以从 ServiceSecurityContext.Current.PrimaryIdentity 获取自定义 IIdentity

希望能解决您的问题!

WCF has a more standard way of achieving the same goal, via a ServiceAuthorizationBehavior.

If you set its PrincipalPermissionMode property to "Custom", it allows you to provide a custom IAuthorizationPolicy via which you can make a custom IPrincipal available to the WCF ServiceSecurityContext. The DispatchRuntime will assign this (your custom) IPrincipal to Thread.CurrentPrincipal - which is what you're after, right?

This is a sample IAuthorizationPolicy implementation:

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

And this is how you declare the ServiceAuthorizationBehavior in the Web.config:

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

Inside your service you can then leverage declarative security via the [PrincipalPermission] attribute, you can get the custom IPrincipal from Thread.CurrentPrincipal, and (alternatively) you can also get the custom IIdentity from ServiceSecurityContext.Current.PrimaryIdentity.

Hope that solves your issue!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文