如何在asp.net下升級用戶身份進行操作

包含 c#, asp.net, vb.net, delphi.net 等 .net framework 的開發討論區
回覆文章
頭像
tim
文章: 1300
註冊時間: 2008年 11月 26日, 00:49

如何在asp.net下升級用戶身份進行操作

文章 tim » 2009年 2月 25日, 12:01

這個是一個比較特殊的應用需求.
要小心使用這個功能, 除非你確定你在做什麼, 不然, 一旦身份升級後, 權限變大之後, 操作不慎很有可能造成一些問題.

請參考這篇技術文章: http://www.dotblogs.com.tw/puma/archive ... roupID=101

程式碼如下:

代碼: 選擇全部

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.IO;

public partial class HighLevelUser : System.Web.UI.Page
{

    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 void Page_Load(Object s, EventArgs e)
    {
        //使用者(ASPNET)
        //下面這行在沒有高權限的使用者會產生,拒絕存取路徑 'e:log.txt'。
        //File.AppendAllText(@"e:log.txt", "F6 Team");

        if (impersonateValidUser("Administrator", "localhost", "123456"))
        {
            Response.Write(string.Format("驗證成功,目前使用者:{0}
", WindowsIdentity.GetCurrent().Name));

            //提高權限(Administrator),才能寫檔
            File.AppendAllText(@"e:log.txt", "F6 Team");

            //還原使用者
            undoImpersonation();

            Response.Write(string.Format("作業完成,目前使用者:{0}
", WindowsIdentity.GetCurrent().Name));
        }
        else
        {
            Response.Write(string.Format("驗證失敗,目前使用者:{0}
", WindowsIdentity.GetCurrent().Name));
        }
    }

    private bool impersonateValidUser(String userName, String domain, String password)
    {
        WindowsIdentity tempWindowsIdentity;
        IntPtr token = IntPtr.Zero;
        IntPtr 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);
        return false;
    }

    private void undoImpersonation()
    {
        impersonationContext.Undo();
    }


}
利用了 LogonUser 這個 API 來進行身份驗證, 並配合 WindowsIdentity.Impersonate() 做身份變換後, 始完成升級用戶進行操作.
多多留言, 整理文章, 把經驗累積下來.....

回覆文章