Проблема с использованием пользовательского принципала и идентичности со службами WCF

Мы используем пользовательский принципал и тип идентификации (ProdigyPrincipal/ProdigyIdentity), потому что нам нужна дополнительная информация в наших программах и службах. В программе мы устанавливаем принципала и личность. При взаимодействии со службой WCF принципал и идентификатор задаются, но после приведения к нашему собственному типу принципал и идентификатор равны нулю.

Я заметил, что между режимом отладки и модульным тестом есть разница. В режиме отладки тип участника и удостоверение имеют тип WindowsPrincipal и WindowsIdentity. В режиме модульного тестирования используются следующие типы: GenericPrincipal и GenericIdenity. В обеих ситуациях при приведении к пользовательскому типу значение равно нулю.

Установка и получение принципала / идентичности осуществляется через 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;
  }

Кто-нибудь знает, почему пользовательский принципал и тип идентификации не могут быть получены из потока?

С уважением, Ганс

1 ответ

У WCF есть более стандартный способ достижения той же цели через ServiceAuthorizationBehavior.

Если вы установите его свойство PrincipalPermissionMode равным "Custom", это позволит вам 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;
    }
}

И вот как вы объявляете ServiceAuthorizationBehavior в Web.config:

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

Внутри вашего сервиса вы можете использовать декларативную безопасность через [PrincipalPermission] атрибут, вы можете получить пользовательский IPrincipal из Thread.CurrentPrincipal и (альтернативно) вы также можете получить ServiceSecurityContext.Current.PrimaryIdentity,

Надеюсь, что решит вашу проблему!

Другие вопросы по тегам