【问题标题】:Declarative security demands - Is SecurityAction.Demand cached?声明性安全需求 - SecurityAction.Demand 是否已缓存?
【发布时间】:2025-12-13 13:55:02
【问题描述】:

我在模拟用户时遇到了问题。我有一个这样声明的方法:

[PrincipalPermission(SecurityAction.Demand, Name=@"DJPITER-PC\Test", Role="LocalTestGroup")]
static void LocalTestGroupOnly()
{
    Console.WriteLine("Inside LocalTestGroupOnly() - {0}", 
        WindowsIdentity.GetCurrent().Name);
}

调用代码是:

WindowsImpersonationContext context = 
        WindowsIdentity.Impersonate(token);

    Console.WriteLine("Calling LocalTestGroupOnly() as {0}", 
        WindowsIdentity.GetCurrent().Name);
    LocalTestGroupOnly();

    context.Undo();

    try
    {
        // Reverted user is displayed properly 
        Console.WriteLine("Calling LocalTestGroupOnly() as {0}", 
            WindowsIdentity.GetCurrent().Name);

        // This method should fail but if succeeds
        LocalTestGroupOnly();
    }
    catch (SecurityException ex)
    {
        Console.WriteLine("Your account lacks permission to that function.");
    }

默认用户不是 LocalTestGroup 的成员。 令牌指示的用户是 LocalTestGroup 的成员。

问题:

第一次调用 LocalTestGroupOnly() 成功,因为令牌指示的用户是 LocalTestGroup 的成员。对 LocalTestGroupOnly() 的第二次调用(作为默认用户)应该会失败,因为默认用户不是“Test”并且它不属于 LocalTestGroup。问题是这个方法也成功了。

如果我单独运行程序 - 无论有没有模拟,我们的行为都是正确的:模拟为“测试”时它成功,而作为默认用户调用时失败。

这里有什么问题?

【问题讨论】:

    标签: .net security permissions code-access-security


    【解决方案1】:

    你能检查Thread.CurrentPrincipal.Identity而不是WindowsIdentity.GetCurrent()吗? PrincipalPermission.Demand() 使用第一个。

    要更改Thread.CurrentPrincipal(或HttpContext.User),您似乎必须在模拟或撤消后显式设置它们。检查here 是否有类似问题。

    【讨论】:

    • 确实:在 context.Undo() 之后我必须添加 Thread.CurrentPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());为什么 Undo() 方法不这样做?看来我没有完全理解 Thread.CurrentPrincipal 和 WindowsImpersonationContext ...
    • 我查找了一些示例,它们都在模拟时明确设置了 Thread.CurrentPrincipal。我在答案中添加了更多信息。