结果证明这种模仿.NET的安全性只允许应用程序级访问。由于COM对象处于系统级别,因此模拟用户仍无法实例化它。我通过右键单击可执行文件并选择“Run As ...”来解决这个问题,程序运行正常。我发现启动程序具有系统访问权限(假设您运行它的用户具有这些凭据)。现在我正在创建一个使用此方法启动此应用程序的外部程序。
感谢您的提示:D
我在虚拟机上安装了Windows XP。它是我的域的一部分,但登录用户只是本地用户。显然,如果我尝试访问网络共享,它将提示用户/密码:
我在虚拟机上测试的程序使用COM对象与来自另一个程序的数据进行交互。如果我没有冒充,我会收到错误,因为我没有正确的凭据。
我对此事进行了一些研究,并发现了许多具有大量VB.NET信息的网站。我用我编写的代码遇到的问题是我可以访问网络资源,但我无法实例化COM对象。
如果我在尝试实例化它之前填写并提交凭据提示(上面),它就可以正常工作。这让我相信必须有一些WinXP凭证提示正在做的事情,我不是。以下是我用于模拟的代码:
Public Sub BeginImpersonation()
Const LOGON32_PROVIDER_DEFAULT As Integer = 0
Const LOGON32_LOGON_INTERACTIVE As Integer = 2
Const SecurityImpersonation As Integer = 2
Dim win32ErrorNumber As Integer
_tokenHandle = IntPtr.Zero
_dupeTokenHandle = IntPtr.Zero
If Not LogonUser(_username, _domainname, _password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, _tokenHandle) Then
win32ErrorNumber = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
Throw New ImpersonationException(win32ErrorNumber, GetErrorMessage(win32ErrorNumber), _username, _domainname)
End If
If Not DuplicateToken(_tokenHandle, SecurityImpersonation, _dupeTokenHandle) Then
win32ErrorNumber = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
CloseHandle(_tokenHandle)
Throw New ImpersonationException(win32ErrorNumber, "Unable to duplicate token!", _username, _domainname)
End If
Dim newId As New System.Security.Principal.WindowsIdentity(_dupeTokenHandle)
_impersonatedUser = newId.Impersonate()
_impersonating = True
End Sub
我也试过向模仿方法发送不同的标志,但似乎没有任何工作。以下是我发现的不同标志:
Enum LOGON32_LOGON
INTERACTIVE = 2
NETWORK = 3
BATCH = 4
SERVICE = 5
UNLOCK = 7
NETWORK_CLEARTEXT = 8
NEW_CREDENTIALS = 9
End Enum
Enum LOGON32_PROVIDER
[DEFAULT] = 0
WINNT35 = 1
WINNT40 = 2
WINNT50 = 3
End Enum
Enum SECURITY_LEVEL
Anonymous = 0
Identification = 1
Impersonation = 2
Delegation = 3
End Enum
我之前遇到过这种情况,并使用了两种不同的解决方案 - 最简单的是使用第三方应用程序:TqcRunas:http://www.quimeras.com/Products/products.asp,它允许您在加密文件中打包所需的creentials。但是,如果密码被强制过期,则会很痛苦。
我使用的另一个解决方案是使用备用凭据调用新进程:
Dim myProcessStartInfo As ProcessStartInfo = New ProcessStartInfo
With myProcessStartInfo
.FileName = "file path and name"
.Domain = "domainname"
.UserName = "username"
'password needs to be a SerureString
Using NewPassword As New Security.SecureString
With NewPassword
For Each c As Char In "password".ToCharArray
.AppendChar(c)
Next c
.MakeReadOnly()
End With
.Password = NewPassword.Copy
End Using
'UseShellExecute must be false for impersonated process
.UseShellExecute = False
End With
Using Process As New System.Diagnostics.Process
With Process
.StartInfo = myProcessStartInfo
.Start()
End With
End Using
根据您的定义,我使用
LogonUser(_username, _domainname, _password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, _tokenHandle)
在我的代码中,通过网络进行身份验证。我像你一样冒充远程盒子上的本地用户。很久以前,我不记得使用这些值的理由。
我做了类似的事情来映射网络驱动器以便在机器之间复制文件。我没有编写代码,但除了两件事之外,它与你的代码几乎相同:
我不知道他们是否会有所作为,但值得一试。以下是相关声明:
Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long
Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long