[ASP.NET] 在ASP.NET中於IIS上模擬不同的執行身份

[ASP.NET] 在ASP.NET中於IIS上模擬不同的執行身份

因為最近在製作的一些功能,有需要模擬不同身份,進入到各個AD伺服器進行驗證與部份功能的執行

在程式開發期間功能都是很正常的,但是一將程式放到IIS上就發生了無法執行的問題

後來發現是因為IIS上,應用程式集區的執行身份為ApplicationPoolIdentity,所以會有權限上不足的地方

我試著將執行身份更改為LocalService或是LocalSystem,但是執行的結果一樣是無法讀取AD伺服器的資料

但是將執行身份更改為AD內的帳號就可以正常執行

001

所以問題應該就是出在IIS的執行身份的識別上

這樣一來,只要能在程式執行的時候,動態去更改執行時的識別身份就可以了

更改識別身份的程式碼,MSDN上已經有可以參考的內容了,可以參考下面的連結頁面

如何在 ASP.NET 應用程式中實作模擬

這邊,我把程式碼拉出來變成一個個別的類別物件,以方便未來的使用

 

1.建立Impersonate物件,程式碼如下

public class Impersonate
{
    public const int LOGON32_LOGON_INTERACTIVE = 2;
    public const int LOGON32_PROVIDER_DEFAULT = 0;

    WindowsImpersonationContext impersonationContext;

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

    public string UserName { get; set; }

    public string Domain { get; set; }

    public string Password { get; set; }

    public Impersonate(string strUserName, string strDomain, string strPwd)
	{
        this.UserName = strUserName;
        this.Domain = strDomain;
        this.Password = strPwd;
	}

    public bool ImpersonateValidUser()
    {
        WindowsIdentity tempWindowsIdentity;
        IntPtr token = IntPtr.Zero;
        IntPtr tokenDuplicate = IntPtr.Zero;

        if (RevertToSelf())
        {
            if (LogonUserA(this.UserName, this.Domain, this.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);

        return false;
    }

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

2.要使用的時候,只要呼叫objImpersonate.ImpersonateValidUser這個Method就可以了

Impersonate objImpersonate = new Impersonate(txtUserName.Text, txtServer.Text, txtPwd.Text);
bool blImpersonate = objImpersonate.ImpersonateValidUser();
        
if (blImpersonate)
{
    // 在這裡放入以特殊身份執行的功能
}

整個使用的檔案如下面附件,內含取出AD帳號與群組的功能,有興趣的人可以下載回去看看嘍

DomainAccount.zip