【问题标题】:Impersonation - Access is denied模拟 - 访问被拒绝
【发布时间】:2011-02-01 01:20:01
【问题描述】:

我在使用模拟从 MVC 网站中删除 PerformanceCounterCategory 时遇到问题。我有一个静态类,当应用程序启动时,它会检查 PerformanceCounterCategory 是否存在,以及它是否包含正确的计数器。如果没有,它会删除该类别并使用所需的计数器重新创建它。

在内置的网络服务器 Cassini 下运行时运行良好,但是当我尝试通过 IIS7 (Vista) 运行它时,出现以下错误:

访问被拒绝
说明:
当前 Web 请求执行期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。
异常详情:
System.ComponentModel.Win32Exception:访问被拒绝

我对代码的使用:

var username = "user";
var password = "password";
var domain = "tempuri.org";

WindowsImpersonationContext impersonationContext;

// if impersonation fails - return
if (!ImpersonateValidUser(username, password, domain, out impersonationContext))
{
    throw new AuthenticationException("Impersonation failed");
}

PerformanceCounterCategory.Delete(PerfCategory);
UndoImpersonation(impersonationContext);

MS 文章中的模拟代码...

private static bool ImpersonateValidUser(string username, string password, 
    string domain, out WindowsImpersonationContext impersonationContext)
{
    const int LOGON32_LOGON_INTERACTIVE = 2;
    const int LOGON32_PROVIDER_DEFAULT = 0;
    WindowsIdentity tempWindowsIdentity;
    var token = IntPtr.Zero;
    var tokenDuplicate = IntPtr.Zero;

    if (RevertToSelf())
    {
        if (LogonUserA(username, domain, password, 
             LOGON32_LOGON_INTERACTIVE, 
             LOGON32_PROVIDER_DEFAULT, ref token) != 0)
        {
            if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
            {
                tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                impersonationContext = tempWindowsIdentity.Impersonate();

                if (impersonationContext != null)
                {
                    CloseHandle(token);
                    CloseHandle(tokenDuplicate);
                    return true;
                }
            }
        }
    }

    if (token != IntPtr.Zero)
        CloseHandle(token);
    if (tokenDuplicate != IntPtr.Zero)
        CloseHandle(tokenDuplicate);

    impersonationContext = null;
    return false;
}



[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName, String lpszDomain, 
    String lpszPassword, int dwLogonType, int dwLogonProvider, 
    ref IntPtr phToken);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, 
    ref IntPtr hNewToken);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);

处理尝试执行 PerformanceCounterCategory.Delete 命令时引发错误。

更新
为了回应大卫的回答,我尝试了以下方法:

  1. 创建了一个名为 PerfMonUser 的新本地用户
  2. 将此用户添加到“性能监视器用户”组中

修改了代码,现在改为:

var username = "PerfMonUser";
var password = "password";
var domain = Environment.MachineName;

WindowsImpersonationContext impersonationContext;

// if impersonation fails - return
if (!ImpersonateValidUser(username, password, domain, out impersonationContext))
{
    throw new AuthenticationException("Impersonation failed");
}

PerformanceCounterCategory.Delete(PerfCategory);
UndoImpersonation(impersonationContext);

...但我仍然收到错误:

异常详细信息:System.ComponentModel.Win32Exception:访问被拒绝

...就行了:

PerformanceCounterCategory.Delete(PerfCategory);

【问题讨论】:

    标签: c# asp.net iis-7 impersonation performancecounter


    【解决方案1】:

    这是因为 PerformanceCounterCategory.Delete 要求您具有管理员权限或者是 Performance Monitor Users 组的成员。详情请见MSDN

    Cassini 默认运行在 NT AUTHORITY\SYSTEM 用户帐户下,显然是 Admin。然而,IIS 在有限的用户帐户下运行,因此它无法访问 PerformanceCounter 调用。您需要让您的“用户”用户成为 Performance Monitor Users 的成员或管理员。

    【讨论】:

    • 您说您尝试将用户添加为性能监视器组的成员。您是否尝试将该用户添加为管理员?那应该是你的下一步。如果可行,那么您知道模拟工作正常,您只需要编辑权限。
    猜你喜欢
    • 1970-01-01
    • 2012-03-12
    • 2012-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-10
    • 2011-10-29
    • 1970-01-01
    相关资源
    最近更新 更多