问题描述
我需要从一个Web应用程序访问远程驱动器。该驱动器无法访问ASP.NET进程,所以我想模拟当前用户的请求。
我看到使用WindowsImpersonationContext一些基本的例子,并尝试以下。
WindowsImpersonationContext impersonationContext = NULL;
尝试
{
impersonationContext =((的WindowsIdentity)User.Identity).Impersonate();
file.SaveAs(文件路径);
}
最后
{
如果(impersonationContext!= NULL)
{
impersonationContext.Undo();
}
}
我仍然得到拒绝访问异常。
我读了一点东西约的LogonUser
,但据我可以告诉你需要一个用户名和密码,以获得该证书。我不是在寻找一个不同的特定用户,只需将当前用户(谁应该有权限访问的文件存储)登录,所以我不认为我真正需要的的LogonUser
API
没有人有任何想法,我缺少的是什么?如若上述code的工作?
我也想指出,包括
<身份冒充=真/>
不工作,但包括
<身份冒充=真的userName =MYNAME密码=MYPASSWORD/>
在的web.config
让我进去。我见过几个人问这是为什么的问题,但我看到没有解释。我想知道,如果它连接到我的问题虽然。
我写的确实是一个辅助类:
公共静态类ImpersonationUtils
{
私人const int的SW_SHOW = 5;
私人const int的TOKEN_QUERY =×0008;
私人const int的TOKEN_DUPLICATE = 0×0002;
私人const int的TOKEN_ASSIGN_PRIMARY = 0×0001;
私人const int的STARTF_USESHOWWINDOW = 00000001;
私人const int的STARTF_FORCEONFEEDBACK = 0x00000040;
私人const int的CREATE_UNI code_ENVIRONMENT = 0x00000400时;
私人const int的TOKEN_IMPERSONATE =×0004;
私人const int的TOKEN_QUERY_SOURCE = 0×0010;
私人const int的TOKEN_ADJUST_PRIVILEGES = 0×0020;
私人const int的TOKEN_ADJUST_GROUPS = 0x0040;
私人const int的TOKEN_ADJUST_DEFAULT = 0x0080;
私人const int的TOKEN_ADJUST_SESSIONID = 0100;
私人const int的STANDARD_RIGHTS_REQUIRED = 0x000F0000;
私人const int的TOKEN_ALL_ACCESS =
STANDARD_RIGHTS_REQUIRED |
TOKEN_ASSIGN_PRIMARY |
TOKEN_DUPLICATE |
TOKEN_IMPERSONATE |
TOKEN_QUERY |
TOKEN_QUERY_SOURCE |
TOKEN_ADJUST_PRIVILEGES |
TOKEN_ADJUST_GROUPS |
TOKEN_ADJUST_DEFAULT |
TOKEN_ADJUST_SESSIONID;
[StructLayout(LayoutKind.Sequential)
私人结构PROCESS_INFORMATION
{
公共IntPtr的hProcess;
公众的IntPtr hThread;
公众诠释dwProcessId;
公众诠释dwThreadId;
}
[StructLayout(LayoutKind.Sequential)
私人结构SECURITY_ATTRIBUTES
{
公众诠释nLength;
公众的IntPtr lpSecurityDescriptor;
公共BOOL bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)
私人结构STARTUPINFO
{
公众诠释CB;
公共字符串升preserved;
公共字符串lpDesktop;
公共字符串lpTitle;
公众诠释DWX;
公众诠释DWY;
公众诠释dwXSize;
公众诠释dwYSize;
公众诠释dwXCountChars;
公众诠释dwYCountChars;
公众诠释dwFillAttribute;
公众诠释dwFlags中;
公共短wShowWindow;
公共短cbReserved2;
公众的IntPtr升preserved2;
公众的IntPtr hStdInput;
公众的IntPtr hStdOutput;
公众的IntPtr hStdError;
}
私人枚举SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
私人枚举TOKEN_TYPE
{
TokenPrimary = 1,
TokenImpersonation
}
[的DllImport(advapi32.dll的,SetLastError =真)
私人静态外部布尔CreateProcessAsUser(
IntPtr的hToken,
串lpApplicationName,
串lpCommandLine,
裁判SECURITY_ATTRIBUTES lpProcessAttributes,
裁判SECURITY_ATTRIBUTES lpThreadAttributes,
布尔bInheritHandles,
INT dwCreationFlags,
IntPtr的lpEnvironment,
串lpCurrentDirectory,
裁判STARTUPINFO lpStartupInfo,
出PROCESS_INFORMATION lpProcessInformation);
[的DllImport(advapi32.dll的,SetLastError =真)
私人静态外部布尔DuplicateTokenEx(
IntPtr的hExistingToken,
INT dwDesiredAccess,
裁判SECURITY_ATTRIBUTES lpThreadAttributes,
INT ImpersonationLevel,
INT dwTokenType,
裁判的IntPtr phNewToken);
[的DllImport(advapi32.dll的,SetLastError =真)
私人静态外部布尔OpenProcessToken(
IntPtr的ProcessHandle,
INT DesiredAccess,
裁判的IntPtr TokenHandle);
[的DllImport(userenv.dll,SetLastError =真)
私人静态外部布尔CreateEnvironmentBlock(
裁判的IntPtr lpEnvironment,
IntPtr的hToken,
布尔bInherit);
[的DllImport(userenv.dll,SetLastError =真)
私人静态外部布尔DestroyEnvironmentBlock(
IntPtr的lpEnvironment);
[的DllImport(KERNEL32.DLL,SetLastError =真)
私有静态的extern BOOL CloseHandle的(
IntPtr的hObject);
私有静态无效LaunchProcessAsUser(字符串CMDLINE,IntPtr的道理,IntPtr的envBlock,诠释的sessionId)
{
VAR PI =新PROCESS_INFORMATION();
VAR saProcess =新SECURITY_ATTRIBUTES();
VAR saThread =新SECURITY_ATTRIBUTES();
saProcess.nLength = Marshal.SizeOf(saProcess);
saThread.nLength = Marshal.SizeOf(saThread);
变种SI =新STARTUPINFO();
si.cb = Marshal.SizeOf(SI);
si.lpDesktop = @WinSta0 \默认;
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;
si.wShowWindow = SW_SHOW;
如果(!CreateProcessAsUser(
令牌,
空值,
CMDLINE,
REF saProcess,
REF saThread,
假,
CREATE_UNI code_ENVIRONMENT,
envBlock,
空值,
REF SI,
出圆周率))
{
抛出新Win32Exception(Marshal.GetLastWin32Error(),CreateProcessAsUser失败);
}
}
私有静态IDisposable的模仿(IntPtr的令牌)
{
VAR身份=新的WindowsIdentity(标记);
返回identity.Impersonate();
}
私有静态的IntPtr GetPrimaryToken(工艺过程)
{
VAR令牌= IntPtr.Zero;
VAR primaryToken = IntPtr.Zero;
如果(OpenProcessToken(process.Handle,TOKEN_DUPLICATE,裁判令牌))
{
VAR SA =新SECURITY_ATTRIBUTES();
sa.nLength = Marshal.SizeOf(SA);
如果(!DuplicateTokenEx(
令牌,
TOKEN_ALL_ACCESS,
REF SA,
(INT)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
(INT)TOKEN_TYPE.TokenPrimary,
裁判primaryToken))
{
抛出新Win32Exception(Marshal.GetLastWin32Error(),DuplicateTokenEx失败);
}
CloseHandle的(标记);
}
其他
{
抛出新Win32Exception(Marshal.GetLastWin32Error(),OpenProcessToken失败);
}
返回primaryToken;
}
私有静态的IntPtr GetEnvironmentBlock(IntPtr的令牌)
{
VAR envBlock = IntPtr.Zero;
如果(!CreateEnvironmentBlock(REF envBlock,令牌,FALSE))
{
抛出新Win32Exception(Marshal.GetLastWin32Error(),CreateEnvironmentBlock失败);
}
返回envBlock;
}
公共静态无效LaunchAsCurrentUser(字符串CMDLINE)
{
VAR方法= Process.GetProcessesByName(资源管理器)FirstOrDefault()。
如果(处理!= NULL)
{
VAR令牌= GetPrimaryToken(过程);
如果(令牌!= IntPtr.Zero)
{
VAR envBlock = GetEnvironmentBlock(标记);
如果(envBlock!= IntPtr.Zero)
{
LaunchProcessAsUser(CMDLINE,令牌,envBlock,process.SessionId);
如果(!DestroyEnvironmentBlock(envBlock))
{
抛出新Win32Exception(Marshal.GetLastWin32Error(),DestroyEnvironmentBlock失败);
}
}
CloseHandle的(标记);
}
}
}
公共静态IDisposable的ImpersonateCurrentUser()
{
VAR方法= Process.GetProcessesByName(资源管理器)FirstOrDefault()。
如果(处理!= NULL)
{
VAR令牌= GetPrimaryToken(过程);
如果(令牌!= IntPtr.Zero)
{
返回冒充(标记);
}
}
抛出新的异常(无法找到Explorer.exe的);
}
}
您可以使用它这样的:
ImpersonationUtils.LaunchAsCurrentUser(记事本);
使用(ImpersonationUtils.ImpersonateCurrentUser())
{
}
更多解释和例子,你可以在这里找到:
I need to access a remote drive from a Web App. The drive isn't accessible to the ASP.NET process, so I want to impersonate the current user for the request.
I saw some basic examples using WindowsImpersonationContext, and have tried the following.
WindowsImpersonationContext impersonationContext = null;
try
{
impersonationContext = ((WindowsIdentity)User.Identity).Impersonate();
file.SaveAs(filePath);
}
finally
{
if (impersonationContext != null)
{
impersonationContext.Undo();
}
}
I'm still getting an access denied exception.
I've read a bit of stuff about LogonUser
, but as far as I can tell you need a user name and password to get credentials from that. I'm not looking to log in as a different specific user, just the current user (who should have permissions to access the file store), so I don't think I actually need the LogonUser
API.
Does anyone have any idea what I'm missing? Should the above code work?
I'd also note that including
<identity impersonate="true" />
doesn't work, but including
<identity impersonate="true" userName="myName" password="myPassword" />
in the web.config
lets me in. I've seen a few people ask questions about why this is, but I've seen no explanation. I'm wondering if it is connected to my problem though.
I wrote a helper class that does it:
public static class ImpersonationUtils
{
private const int SW_SHOW = 5;
private const int TOKEN_QUERY = 0x0008;
private const int TOKEN_DUPLICATE = 0x0002;
private const int TOKEN_ASSIGN_PRIMARY = 0x0001;
private const int STARTF_USESHOWWINDOW = 0x00000001;
private const int STARTF_FORCEONFEEDBACK = 0x00000040;
private const int CREATE_UNICODE_ENVIRONMENT = 0x00000400;
private const int TOKEN_IMPERSONATE = 0x0004;
private const int TOKEN_QUERY_SOURCE = 0x0010;
private const int TOKEN_ADJUST_PRIVILEGES = 0x0020;
private const int TOKEN_ADJUST_GROUPS = 0x0040;
private const int TOKEN_ADJUST_DEFAULT = 0x0080;
private const int TOKEN_ADJUST_SESSIONID = 0x0100;
private const int STANDARD_RIGHTS_REQUIRED = 0x000F0000;
private const int TOKEN_ALL_ACCESS =
STANDARD_RIGHTS_REQUIRED |
TOKEN_ASSIGN_PRIMARY |
TOKEN_DUPLICATE |
TOKEN_IMPERSONATE |
TOKEN_QUERY |
TOKEN_QUERY_SOURCE |
TOKEN_ADJUST_PRIVILEGES |
TOKEN_ADJUST_GROUPS |
TOKEN_ADJUST_DEFAULT |
TOKEN_ADJUST_SESSIONID;
[StructLayout(LayoutKind.Sequential)]
private struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
[StructLayout(LayoutKind.Sequential)]
private struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)]
private struct STARTUPINFO
{
public int cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public int dwX;
public int dwY;
public int dwXSize;
public int dwYSize;
public int dwXCountChars;
public int dwYCountChars;
public int dwFillAttribute;
public int dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
private enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
private enum TOKEN_TYPE
{
TokenPrimary = 1,
TokenImpersonation
}
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool CreateProcessAsUser(
IntPtr hToken,
string lpApplicationName,
string lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
bool bInheritHandles,
int dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool DuplicateTokenEx(
IntPtr hExistingToken,
int dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
int ImpersonationLevel,
int dwTokenType,
ref IntPtr phNewToken);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(
IntPtr ProcessHandle,
int DesiredAccess,
ref IntPtr TokenHandle);
[DllImport("userenv.dll", SetLastError = true)]
private static extern bool CreateEnvironmentBlock(
ref IntPtr lpEnvironment,
IntPtr hToken,
bool bInherit);
[DllImport("userenv.dll", SetLastError = true)]
private static extern bool DestroyEnvironmentBlock(
IntPtr lpEnvironment);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(
IntPtr hObject);
private static void LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock, int sessionId)
{
var pi = new PROCESS_INFORMATION();
var saProcess = new SECURITY_ATTRIBUTES();
var saThread = new SECURITY_ATTRIBUTES();
saProcess.nLength = Marshal.SizeOf(saProcess);
saThread.nLength = Marshal.SizeOf(saThread);
var si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = @"WinSta0\Default";
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;
si.wShowWindow = SW_SHOW;
if (!CreateProcessAsUser(
token,
null,
cmdLine,
ref saProcess,
ref saThread,
false,
CREATE_UNICODE_ENVIRONMENT,
envBlock,
null,
ref si,
out pi))
{
throw new Win32Exception(Marshal.GetLastWin32Error(), "CreateProcessAsUser failed");
}
}
private static IDisposable Impersonate(IntPtr token)
{
var identity = new WindowsIdentity(token);
return identity.Impersonate();
}
private static IntPtr GetPrimaryToken(Process process)
{
var token = IntPtr.Zero;
var primaryToken = IntPtr.Zero;
if (OpenProcessToken(process.Handle, TOKEN_DUPLICATE, ref token))
{
var sa = new SECURITY_ATTRIBUTES();
sa.nLength = Marshal.SizeOf(sa);
if (!DuplicateTokenEx(
token,
TOKEN_ALL_ACCESS,
ref sa,
(int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
(int)TOKEN_TYPE.TokenPrimary,
ref primaryToken))
{
throw new Win32Exception(Marshal.GetLastWin32Error(), "DuplicateTokenEx failed");
}
CloseHandle(token);
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error(), "OpenProcessToken failed");
}
return primaryToken;
}
private static IntPtr GetEnvironmentBlock(IntPtr token)
{
var envBlock = IntPtr.Zero;
if (!CreateEnvironmentBlock(ref envBlock, token, false))
{
throw new Win32Exception(Marshal.GetLastWin32Error(), "CreateEnvironmentBlock failed");
}
return envBlock;
}
public static void LaunchAsCurrentUser(string cmdLine)
{
var process = Process.GetProcessesByName("explorer").FirstOrDefault();
if (process != null)
{
var token = GetPrimaryToken(process);
if (token != IntPtr.Zero)
{
var envBlock = GetEnvironmentBlock(token);
if (envBlock != IntPtr.Zero)
{
LaunchProcessAsUser(cmdLine, token, envBlock, process.SessionId);
if (!DestroyEnvironmentBlock(envBlock))
{
throw new Win32Exception(Marshal.GetLastWin32Error(), "DestroyEnvironmentBlock failed");
}
}
CloseHandle(token);
}
}
}
public static IDisposable ImpersonateCurrentUser()
{
var process = Process.GetProcessesByName("explorer").FirstOrDefault();
if (process != null)
{
var token = GetPrimaryToken(process);
if (token != IntPtr.Zero)
{
return Impersonate(token);
}
}
throw new Exception("Could not find explorer.exe");
}
}
You can use it like that:
ImpersonationUtils.LaunchAsCurrentUser("notepad");
using (ImpersonationUtils.ImpersonateCurrentUser())
{
}
More explanations and examples you can find here :
Impersonating CurrentUser from SYSTEM
这篇关于使用WindowsImpersonationContext访问网络驱动器模拟当前用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!