假冒 - 访问被拒绝

时间:2010-03-26 05:47:23

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

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

在内置的Web服务器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. 将此用户添加到“性能监视器用户”组
  3. 修改了代码,现在读取:

    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);
    

1 个答案:

答案 0 :(得分:2)

这是因为PerformanceCounterCategory.Delete要求您具有管理员权限或者是Performance Monitor Users组的成员。有关详细信息,请参阅MSDN

默认情况下,Cassini在NT AUTHORITY \ SYSTEM用户帐户下运行,显然是Admin。然而,IIS在有限的用户帐户下运行,因此它无法访问PerformanceCounter调用。您需要使“用户”用户成为性能监视器用户或管理员的成员。