CODE-C#變身術懶人包
8 |
以前老覺得,用C#寫身份切換(用不同身份存取資源)程式得借重API,有一堆細節要處理,麻煩得很。
這回發了狠,一口氣把複雜工作通通裝在一個Class裡,呼叫時只要傳入帳號、密碼和網域,取回WindowsImpersonationContext,一切搞定。
就叫它【C#變身術懶人包】吧!
//REF: http://support.microsoft.com/kb/319615
public class ImpersonateHelper
{
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUser(string lpszUsername,
string lpszDomain, string lpszPassword, int dwLogonType,
int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto,
SetLastError = true)]
private static extern bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto,
SetLastError = true)]
public extern static bool DuplicateToken(IntPtr existingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL, ref IntPtr duplicateTokenHandle);
// logon types
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
// logon providers
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_PROVIDER_WINNT50 = 3;
const int LOGON32_PROVIDER_WINNT40 = 2;
const int LOGON32_PROVIDER_WINNT35 = 1;
public static IntPtr GetDupToken(string userName, string password,
string domain)
{
IntPtr token = IntPtr.Zero;
IntPtr dupToken = IntPtr.Zero;
bool isSuccess = LogonUser(
userName,
domain,
password,
LOGON32_LOGON_NEW_CREDENTIALS,
LOGON32_PROVIDER_DEFAULT,
ref token);
if (!isSuccess)
throw new ApplicationException(
"Failed to LogonUser, Code = " +
Marshal.GetLastWin32Error());
isSuccess = DuplicateToken(token, 2, ref dupToken);
if (!isSuccess)
throw new ApplicationException(
"Failed to DuplicateToken, Code = " +
Marshal.GetLastWin32Error());
return dupToken;
}
public static WindowsImpersonationContext
GetImpersonationContext(
string userName, string password, string domainName)
{
return new WindowsIdentity(
ImpersonateHelper.GetDupToken(userName, password, domainName)
).Impersonate();
}
}
static void test()
{
Dictionary<string, string> latestList = new Dictionary<string, string>();
using (WindowsImpersonationContext wic =
ImpersonateHelper.GetImpersonationContext("username", "pwd",
"domainOrRemoteServerIp"))
{
foreach (string f in
Directory.GetFiles(@"\\remoteServer\Folder", "*.txt"))
Console.WriteLine(f);
wic.Undo();
}
}
Comments
# by alimalik199@gmail.com
Linux Web Hosting For Small Businesses. http://twurl.nl/1ri4oo
# by 過路客
domainOrRemoveServerIp=DomainOrRemoteServerIP ?
# by Jeffrey
to 過路客, 謝謝指正,打錯字了
# by Xman
請問版大,您是否有使用Case tool記錄開發系統的相關文件? 如果有的話,是用那種工具呢?謝謝。
# by Jeffrey
to Xman, 其實我不算軟體工程方法論的信徒(還有點像叛徒),純粹是愛Coding而已, 說明文件不講究格式規範,以清楚陳述為主(跟寫Blog一樣爾偶還不忘搞笑),工作上的文件只用VSS保留改版歷程而已。但我的程式碼註解量蠻多的,積陰德順便拯救自己的健忘。
# by Dogg04
請問為什麼我沒辦法使用 (WindowsImpersonationContext wic = ImpersonateHelper.GetImpersonationContext("administrator", "easyuse", "192.168.66.128") 登入呢?? 會出現"語彙基元不可以為零" ...是我哪邊參數給錯了嗎?
# by Dogg04
版大..剛剛的問題解決了...但是還有另一個問題~~ 為什麼我就算密碼或是登入帳號亂輸入~~"isSuccess" 參數仍然是 "true" 呢??
# by Kim
Dear 黑大 剛測試程式碼,若是要存取跨網域,要使用下面的設定 LOGON32_LOGON_INTERACTIVE 環境只能Run在xp,2003...