从 WindowsIdentity 和 Thread.CurrentPrincipal 检索 WindowsPrincipal 有啥区别?

Posted

技术标签:

【中文标题】从 WindowsIdentity 和 Thread.CurrentPrincipal 检索 WindowsPrincipal 有啥区别?【英文标题】:What's the difference between retrieving WindowsPrincipal from WindowsIdentity and Thread.CurrentPrincipal?从 WindowsIdentity 和 Thread.CurrentPrincipal 检索 WindowsPrincipal 有什么区别? 【发布时间】:2011-06-01 14:19:42 【问题描述】:

我正在尝试找出为什么基于属性的安全性在 WCF 中无法正常工作,我怀疑这可能与以下原因有关:

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")]

帮助表示赞赏。

【问题讨论】:

我对那个类不是很熟悉,但是我想知道比较两个身份的 .Token 属性是否会显示出差异?一个是本地系统帐户,另一个是网络帐户...类似的。 谢谢格雷格。令牌是“与当前执行线程关联的访问令牌的句柄”——它们确实不同。不知道这意味着什么,除了他们有不同的指针。每次代码运行时,令牌都彼此不同,并且与之前的执行不同。我预料到了这一点。对于 IsSystem 属性,两者都返回 true。 Owner 属性(SID 或安全标识符)的值也相同。两个小时后,我失去了生存的意愿。 您是否在 Windows Vista 或更高版本上运行?我想知道这是否与 UAC 的邪恶有关;我认为 Windows 在登录期间会创建一个假用户,该用户看起来与现有用户大部分但并不完全相同。您可以通过以管理员身份运行应用程序并查看是否可以解决问题来测试这是否是问题。 在 MSDN 上查找客户端模拟。 【参考方案1】:

也许是因为这不是同一个类。

看看 MSDN:

Thread.CurrentPrincipal IPrincipal IsInRole WindowsPrincipal IsInRole

所以,如果有不同的类,可能会有不同的实现。

编辑:

我试过这段代码:

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\t1\t2\t3",
        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\t1\t2\t3",
            reference.Value,
            principalcurrent.IsInRole(reference.Value),
            principalFixe.IsInRole(reference.Value),
            principalThread.IsInRole(reference.Value));
    

这里是the result

如您所见,我没有采用不同方式的相同组。 所以(因为我是本地机器的管理员)我认为 WindowsIdentity.GetCurrent 将从 AD 获取用户,而 WindowsPrincipal(WindowsIdentity("")) 将从本地机器获取用户。

在我的 webapp 中,我的授权可能最低(我认为)。 但是,我对控制台应用程序没有任何解释......

这只是假设,但这是连贯的。

【讨论】:

WindowsPrincipal 实现了IPrincipal 接口。 Implements 不代表两个 implementation 相同。 我已经编辑了我的第一个回复,以展示我想说的示例。【参考方案2】:

我相信登录用户和运行应用程序(线程)的帐户之间存在差异。这些并不总是相同的。

【讨论】:

【参考方案3】:

我承认这是一个相当丑陋的解决方法,但如果所有其他方法都失败了,你可以替换:

principal = (WindowsPrincipal)Thread.CurrentPrincipal;

类似的东西

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

如果这不起作用,它可能至少有助于说明问题出在哪里。

但我无法想象它会失败,因为它所做的事情(在相关的地方)与有效的行完全相同:我假设 Thread.CurrentPrincipal.Identity.Name"ksarfo"

【讨论】:

以上是关于从 WindowsIdentity 和 Thread.CurrentPrincipal 检索 WindowsPrincipal 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 IIS 从 Blazor 服务器获取 WindowsIdentity.RunImpersonated(token, action) 的 HttpContext(或 AccessToken)

WindowsIdentity.Impersonate 和 PostBack 问题

WindowsIdentity.GetCurrent().Impersonate() 做啥

如何使用 WindowsIdentity 和 SQL Server 集成安全设置表单身份验证

C# - 获取 ASPNET WindowsIdentity

WindowsIdentity winId = (WindowsIdentity)HttpContext.Current.User.Identity;如何使这个演员工作;目前它失败了