首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> 關於ASP.NET

ASP.NET 模擬其他使用者身分執行系統關機(P/Invoke Windows API)

     編輯:關於ASP.NET

完整程式碼

using System;
using System.Security.Principal;
using System.Runtime.InteropServices;

public class Impersonate
{
    #region 模擬使用者
    private WindowsImpersonationContext impersonationContext;
    private const int LOGON32_LOGON_INTERACTIVE = 2;
    private const int LOGON32_PROVIDER_DEFAULT = 0;

    [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
    private static extern int LogonUser(string lpszUserName, string lpszDomain, string lpszPassword,
        int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

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

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

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

    public bool ImpersonateUser(string userName, string password, string domain)
    {
        IntPtr token = IntPtr.Zero, tokenDuplicate = IntPtr.Zero;
        if (RevertToSelf())
        {
            if (LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0)
            {
                if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                {
                    WindowsIdentity wi = new WindowsIdentity(tokenDuplicate);
                    impersonationContext = wi.Impersonate();
                    if (impersonationContext != null)
                    {
                        CloseHandle(tokenDuplicate); CloseHandle(token);
                        return true;
                    }
                }
            }
        }
        if (tokenDuplicate != IntPtr.Zero) CloseHandle(tokenDuplicate);
        if (token != IntPtr.Zero) CloseHandle(token);
        return false;
    }

    public void UndoImpersonation() { impersonationContext.Undo(); }
    #endregion

    #region 關機
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    private struct TokPriv1Luid { public int Count; public long Luid; public int Attr; }

    [DllImport("kernel32.dll", ExactSpelling = true)] private static extern IntPtr GetCurrentThread();
    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] private static extern bool OpenThreadToken(IntPtr h, int acc, bool openAsSelf, ref IntPtr phtok);
    [DllImport("advapi32.dll", SetLastError = true)] private static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] private static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
    [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)] private static extern bool ExitWindowsEx(int flg, int rea);
    [DllImport("advapi32.dll")] private static extern bool InitiateSystemShutdown(string machinename, string message, long timeout, bool forceAppsClosed, bool rebootAfterShutdown);

    private const int SE_PRIVILEGE_ENABLED = 0x00000002;
    private const int TOKEN_QUERY = 0x00000008;
    private const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
    private const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
    private const int EWX_SHUTDOWN = 0x00000001;
    private const int EWX_FORCE = 0x00000004;

    public bool ShutDown()
    {
        TokPriv1Luid tp = new TokPriv1Luid();
        IntPtr hproc = GetCurrentThread(); // 注意:用 Thread Token 而非 Process Token
        IntPtr htok = IntPtr.Zero;
        bool result = OpenThreadToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, true, ref htok);
        tp.Count = 1; tp.Luid = 0; tp.Attr = SE_PRIVILEGE_ENABLED;
        result = LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
        result = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
        result = InitiateSystemShutdown("", "", 60, true, false); // 60 秒倒數、強制關閉應用、不重開機
        return result;
    }
    #endregion
}

關鍵技術點

  • 模擬使用者:LogonUser → DuplicateToken → WindowsIdentity.Impersonate。
  • 關機權限:必須開啟 執行緒權杖 (OpenThreadToken) 而非進程權杖,啟用 SeShutdownPrivilege 特權。
  • 呼叫 InitiateSystemShutdown 發起關機,可指定延遲秒數、強制關閉應用程式、是否重開機。

安全性警示

此功能極度敏感,僅限受信任的管理工具在嚴格存取控制下使用,切勿暴露於公開網頁介面。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved