[英]How to use LogonUser properly to impersonate domain user from workgroup client
ASP.NET: Impersonate against a domain on VMWare ASP.NET:模拟 VMWare 上的域
This question is what I am asking, but the answer does not provide details on how the _token is derived.这个问题是我要问的,但答案没有提供有关 _token 是如何派生的详细信息。 It seems to only use
WindowsIdentity.GetCurrent().Token
so there's no impersonation happening.它似乎只使用
WindowsIdentity.GetCurrent().Token
所以没有模拟发生。
Can I impersonate a user on a different Active Directory domain in .NET? 我可以在 .NET 中模拟不同 Active Directory 域上的用户吗?
This next question has conflicting answers, with the accepted one bearing a comment "I'm beginning to suspect that my problem lies elsewhere."下一个问题的答案相互矛盾,接受的答案带有评论“我开始怀疑我的问题出在其他地方。” Not helpful.
没有帮助。
LogonUser works only for my domain LogonUser 仅适用于我的域
This next question seems to imply it is not possible, but it deals with 2 domains so I am not sure if it is relevant.下一个问题似乎暗示这是不可能的,但它涉及 2 个域,所以我不确定它是否相关。
My real question is:我真正的问题是:
What I have tried so far is, using the code from http://msdn.microsoft.com/en-us/library/chf6fbt4%28v=VS.80%29.aspx到目前为止我尝试过的是,使用来自http://msdn.microsoft.com/en-us/library/chf6fbt4%28v=VS.80%29.aspx的代码
bool returnValue = LogonUser(user, domain, password,
LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT,
ref tokenHandle);
// after this point, returnValue = false
The Win32 error is Win32错误是
Logon failure: unknown user name or bad password
登录失败:未知用户名或错误密码
Very few posts suggest using LOGON_TYPE_NEW_CREDENTIALS
instead of LOGON_TYPE_NETWORK
or LOGON_TYPE_INTERACTIVE
. 很少有帖子建议使用
LOGON_TYPE_NEW_CREDENTIALS
而不是LOGON_TYPE_NETWORK
或LOGON_TYPE_INTERACTIVE
。 I had an impersonation issue with one machine connected to a domain and one not, and this fixed it. 我有一个假冒问题,一台机器连接到一个域而一个没有,这就解决了。 The last code snippet in this post suggests that impersonating across a forest does work, but it doesn't specifically say anything about trust being set up.
这篇文章中的最后一个代码片段表明模仿森林确实有效,但它没有具体说明建立信任的任何内容。 So this may be worth trying:
所以这可能值得尝试:
const int LOGON_TYPE_NEW_CREDENTIALS = 9;
const int LOGON32_PROVIDER_WINNT50 = 3;
bool returnValue = LogonUser(user, domain, password,
LOGON_TYPE_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50,
ref tokenHandle);
MSDN says that LOGON_TYPE_NEW_CREDENTIALS
only works when using LOGON32_PROVIDER_WINNT50
. MSDN表示
LOGON_TYPE_NEW_CREDENTIALS
仅在使用LOGON32_PROVIDER_WINNT50
时LOGON32_PROVIDER_WINNT50
。
this works for me, full working example (I wish more people would do this): 这适用于我,完整的工作示例(我希望更多的人会这样做):
//logon impersonation
using System.Runtime.InteropServices; // DllImport
using System.Security.Principal; // WindowsImpersonationContext
using System.Security.Permissions; // PermissionSetAttribute
...
class Program {
// obtains user token
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
// closes open handes returned by LogonUser
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
public void DoWorkUnderImpersonation() {
//elevate privileges before doing file copy to handle domain security
WindowsImpersonationContext impersonationContext = null;
IntPtr userHandle = IntPtr.Zero;
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_LOGON_INTERACTIVE = 2;
string domain = ConfigurationManager.AppSettings["ImpersonationDomain"];
string user = ConfigurationManager.AppSettings["ImpersonationUser"];
string password = ConfigurationManager.AppSettings["ImpersonationPassword"];
try {
Console.WriteLine("windows identify before impersonation: " + WindowsIdentity.GetCurrent().Name);
// if domain name was blank, assume local machine
if (domain == "")
domain = System.Environment.MachineName;
// Call LogonUser to get a token for the user
bool loggedOn = LogonUser(user,
domain,
password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
ref userHandle);
if (!loggedOn) {
Console.WriteLine("Exception impersonating user, error code: " + Marshal.GetLastWin32Error());
return;
}
// Begin impersonating the user
impersonationContext = WindowsIdentity.Impersonate(userHandle);
Console.WriteLine("Main() windows identify after impersonation: " + WindowsIdentity.GetCurrent().Name);
//run the program with elevated privileges (like file copying from a domain server)
DoWork();
} catch (Exception ex) {
Console.WriteLine("Exception impersonating user: " + ex.Message);
} finally {
// Clean up
if (impersonationContext != null) {
impersonationContext.Undo();
}
if (userHandle != IntPtr.Zero) {
CloseHandle(userHandle);
}
}
}
private void DoWork() {
//everything in here has elevated privileges
//example access files on a network share through e$
string[] files = System.IO.Directory.GetFiles(@"\\domainserver\e$\images", "*.jpg");
}
}
I was having the same problem. 我遇到了同样的问题。 Don't know if you've solved this or not, but what I was really trying to do was access a network share with AD credentials.
不知道你是否已经解决了这个问题,但我真正想做的是使用AD凭据访问网络共享。
WNetAddConnection2()
is what you need to use in that case. 在这种情况下,您需要使用
WNetAddConnection2()
。
I have been successfull at impersonating users in another domain, but only with a trust set up between the 2 domains. 我成功地模仿了另一个域中的用户,但只是在两个域之间建立了信任。
var token = IntPtr.Zero;
var result = LogonUser(userID, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token);
if (result)
{
return WindowsIdentity.Impersonate(token);
}
Invalid login/password could be also related to issues in your DNS server - that's what happened to me and cost me good 5 hours of my life. 无效的登录/密码也可能与您的DNS服务器中的问题有关 - 这就是发生在我身上的事情,这让我花了5个小时的时间。 See if you can specify ip address instead on domain name.
看看你是否可以在域名上指定IP地址。
It's better to use a SecureString: 最好使用SecureString:
var password = new SecureString();
var phPassword phPassword = Marshal.SecureStringToGlobalAllocUnicode(password);
IntPtr phUserToken;
LogonUser(username, domain, phPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out phUserToken);
And: 和:
Marshal.ZeroFreeGlobalAllocUnicode(phPassword);
password.Dispose();
Function definition: 功能定义:
private static extern bool LogonUser(
string pszUserName,
string pszDomain,
IntPtr pszPassword,
int dwLogonType,
int dwLogonProvider,
out IntPtr phToken);
The problem I encountered was when my workstation was on one domain, but I needed to authenticate to a server on a different domain:我遇到的问题是当我的工作站在一个域上时,但我需要向另一个域上的服务器进行身份验证:
"Exception impersonating user, error code: 1326"
"Exception impersonating user, error code: 1326"
LOGON32_LOGON_NEW_CREDENTIALS
as a fallback to Impersonate/LogonUser()LOGON32_LOGON_NEW_CREDENTIALS
作为对 Impersonate/LogonUser() 的回退Impersonation.cs模拟.cs
using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
namespace TestDBAccess
{
public class Impersonation : IDisposable
{
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String Username, String Domain, String Password, int LogonType, int LogonProvider, out IntPtr Token);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
public const int LOGON32_PROVIDER_DEFAULT = 0;
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_LOGON_NETWORK = 3;
public const int LOGON32_LOGON_BATCH = 4;
public const int LOGON32_LOGON_SERVICE = 5;
public const int LOGON32_LOGON_UNLOCK = 7;
public const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8;
public const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
private WindowsImpersonationContext impersonationContext = null;
private IntPtr userHandle = IntPtr.Zero;
public Impersonation(string user, string domain, string password)
{
// Extract domain/username from user string
string[] principal = user.Split('\\');
if (principal.Length == 2)
{
domain = principal[0];
user = principal[1];
}
if (string.IsNullOrEmpty(domain))
domain = GetDefaultDomain();
// Call LogonUser to get a token for the user
bool loggedOn =
LogonUser(user, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, out userHandle);
if (!loggedOn)
{
int ierr = Marshal.GetLastWin32Error();
if (ierr == 1326)
{
loggedOn =
LogonUser(user, domain, password, LOGON32_LOGON_NEW_CREDENTIALS,
LOGON32_PROVIDER_DEFAULT, out userHandle);
}
if (!loggedOn)
throw new Exception("Exception impersonating user, error code: " + Marshal.GetLastWin32Error());
}
// Begin impersonating the user
impersonationContext = WindowsIdentity.Impersonate(userHandle);
}
public static string GetDefaultDomain ()
{
return System.Environment.UserDomainName;
}
public void Dispose()
{
// Clean up
if (impersonationContext != null)
impersonationContext.Undo();
if (userHandle != IntPtr.Zero)
CloseHandle(userHandle);
}
}
}
ExampleClient.cs ExampleClient.cs
Impersonation Impersonation = null;
try
{
Impersonation = new Impersonation(username, null, password);
LogMsg("Attempting to connect to (" + dbInstance.instance + ")...");
using (SqlConnection connection = new SqlConnection(connString))
{
connection.Open();
string sql = edtTestSql.Text;
LogMsg("Attempting to query (" + sql + ")...");
using (SqlCommand command = new SqlCommand(sql, connection))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
LogMsg("next row: " + DumpRow(reader));
}
}
}
}
catch (Exception ex)
{
LogMsg(ex.Message);
}
finally
{
if (Impersonation != null)
Impersonation.Dispose();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.