模拟 - 访问被拒绝

发布于 2024-08-26 19:53:03 字数 3552 浏览 2 评论 0原文

我在使用模拟从 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 命令时,会引发错误。

更新
为了回应 David 的回答,我尝试了以下操作:

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

I am having trouble using impersonation to delete a PerformanceCounterCategory from an MVC website. I have a static class and when the application starts it checks whether or not a PerformanceCounterCategory exists, and if it contains the correct counters. If not, it deletes the category and creates it again with the required counters.

It works fine when running under the built in webserver Cassini, but when i try run it through IIS7 (Vista) i get the following error:

Access is denied
Description:
An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details:
System.ComponentModel.Win32Exception: Access is denied

My use of the code:

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

The impersonation code from an MS article...

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

The error is thrown when processing tries to execute the PerformanceCounterCategory.Delete command.

Update
In response to David's answer i tried the following:

  1. Created a new local user named PerfMonUser
  2. Added this user to the "Performance Monitor Users" group

Modified the code so it now reads :

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

... but i'm still getting the error:

Exception Details: System.ComponentModel.Win32Exception: Access is denied

...on the line:

PerformanceCounterCategory.Delete(PerfCategory);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无言温柔 2024-09-02 19:53:03

这是因为 PerformanceCounterCategory.Delete 要求您具有管理员权限或者是性能监视器用户组的成员。有关详细信息,请参阅 MSDN

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

This is because PerformanceCounterCategory.Delete requires you to have either Administrator privileges or be a member of the Performance Monitor Users group. See MSDN for details.

Cassini runs under the NT AUTHORITY\SYSTEM user account by default, which is obviously Admin. IIS however runs under a limited user account, so it won't have access to PerformanceCounter calls. You'll need to make your "user" user either a member of Performance Monitor Users or an Administrator.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文