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

Мы используем пользовательский принципал и тип идентификации (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;
  }

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

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

1 Ответ

8 голосов
/ 07 мая 2011

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, и (альтернативно) вы также можете получить кастом IIdentity от ServiceSecurityContext.Current.PrimaryIdentity.

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

...