15

Я пытаюсь выяснить, почему безопасность на основе атрибута не работает, как я бы ожидать в WCF, и я подозреваю, что это, возможно, что-то делать со следующим:В чем разница между извлечением WindowsPrincipal из WindowsIdentity и Thread.CurrentPrincipal?

AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal); 

var identity = new WindowsIdentity("ksarfo"); 
var principal = new WindowsPrincipal(identity); 
Console.WriteLine("\nChecking whether current user [" + identity.Name + "] is member of [" + groupName + "]"); 
Console.WriteLine(principal.IsInRole(groupName)); // returns true 

principal = (WindowsPrincipal)Thread.CurrentPrincipal; 
identity = (WindowsIdentity) principal.Identity; 
Console.WriteLine("\nChecking whether current user [" + identity.Name + "] is member of [" + groupName + "]"); 
Console.WriteLine(principal.IsInRole(groupName)); // returns false 

Я не понимаю, почему результаты различаются для вызова функции:

principal.IsInRole(groupName) 

для полноты точки, в которой коды фактически не удается здесь:

PrincipalPermission(SecurityAction.Demand, Role = "PortfolioManager")] 

Помогите оценить.

+0

Я не очень хорошо знаком с этим классом, но мне интересно, сравнивает ли свойство .Token этих двух тождеств? Является ли локальная системная учетная запись, а другая - сетевой учетной записью ... что-то вроде этого. – Greg

+0

Спасибо, Грег. Токен - это «дескриптор токена доступа, связанного с текущим потоком выполнения» - они различаются. Не уверен, что это значит, кроме того, что у них разные указатели. Каждый раз, когда код запускает токены, они отличаются друг от друга и предыдущим исполнением. Я ожидал этого. Оба возвращают true для свойства IsSystem. Значения для свойства Owner (SID или идентификатор безопасности) также идентичны. Два часа я теряю желание жить. –

+1

Вы работаете в Windows Vista или выше? Интересно, может ли это быть связано с злом UAC; Я думаю, что окна создают поддельный пользователь во время входа в систему, который выглядит в основном, но не совсем так же, как и у существующего пользователя. Вы можете проверить, если это проблема, запустив приложение в качестве администратора и видя, устраняет проблему. – Brian

ответ

5

Возможно, это потому, что это не те же классы.

Посмотрите на MSDN:

Так что, если есть дифферент классы, может быть, есть реализации дифферент.

EDIT:

У меня попробовать этот код:

public class InGroup 
{ 
    public string Name { get; set; } 
    public bool Current { get; set; } 
    public bool Fixe { get; set; } 
    public bool Thread { get; set; } 
} 

WindowsIdentity current = System.Security.Principal.WindowsIdentity.GetCurrent(); 
WindowsPrincipal principalcurrent = new WindowsPrincipal(current); 

WindowsIdentity fixe = new WindowsIdentity("JW2031"); 
WindowsPrincipal principalFixe = new WindowsPrincipal(fixe); 

IPrincipal principalThread = System.Threading.Thread.CurrentPrincipal; 

List<InGroup> ingroups = new List<InGroup>(); 
foreach (IdentityReference item in current.Groups) 
{ 
    IdentityReference reference = item.Translate(typeof(NTAccount)); 
    Console.WriteLine("{0}\t{1}\t{2}\t{3}", 
     reference.Value, 
     principalcurrent.IsInRole(reference.Value), 
     principalFixe.IsInRole(reference.Value), 
     principalThread.IsInRole(reference.Value)); 

    ingroups.Add(new InGroup() 
    { 
     Name = reference.Value, 
     Current = principalcurrent.IsInRole(reference.Value), 
     Fixe = principalFixe.IsInRole(reference.Value), 
     Thread = principalThread.IsInRole(reference.Value) 
    }); 
} 
foreach (IdentityReference item in fixe.Groups) 
{ 
    IdentityReference reference = item.Translate(typeof(NTAccount)); 
    if (ingroups.FindIndex(g => g.Name == reference.Value) == -1) 
    { 
     ingroups.Add(new InGroup() 
     { 
      Name = reference.Value, 
      Current = principalcurrent.IsInRole(reference.Value), 
      Fixe = principalFixe.IsInRole(reference.Value), 
      Thread = principalThread.IsInRole(reference.Value) 
     }); 
     Console.WriteLine("{0}\t{1}\t{2}\t{3}", 
      reference.Value, 
      principalcurrent.IsInRole(reference.Value), 
      principalFixe.IsInRole(reference.Value), 
      principalThread.IsInRole(reference.Value)); 
    } 
} 

А вот the result

Как вы можете видеть, я не имею те же группы с Дифференц способами. Итак, (поскольку я являюсь администратором моего локального компьютера), я думаю, что WindowsIdentity.GetCurrent получит пользователя от AD и WindowsPrincipal (WindowsIdentity ("")) получит пользователя с локальной машины.

В моем webapp я получил самую низкую авторизацию (я думаю). Но у меня нет пояснений к consoleapp ...

Это только предположения, но это согласовано.

+0

'WindowsPrincipal' реализует интерфейс' IPrincipal'. – Brian

+0

Реализация не означает, что две реализации одинаковы. – kerrubin

+0

Я отредактировал свой первый ответ, чтобы показать пример того, что я хочу сказать. – kerrubin

1

Я признаю, что это довольно уродливые обходной путь, но если все остальное терпит неудачу вы могли бы заменить:

principal = (WindowsPrincipal)Thread.CurrentPrincipal; 

с чем-то вроде

principal = new WindowsPrincipal(new WindowsIdentity(Thread.CurrentPrincipal.Identity.Name)); 

Если это не сработает, то это будет, вероятно, по крайней мере, быть поучительным в том, чтобы показывать, где все идет не так.

Но я не могу представить, чтобы это не сработало, так как оно делает то же самое (где это актуально), как линия, которая работала: Я предполагаю, что Thread.CurrentPrincipal.Identity.Name - это "ksarfo".

3

Я считаю, что разница между зарегистрированным пользователем и учетной записью, запускающей приложение (поток). Они не всегда будут одинаковыми.