vb.net之使用凭据打开远程共享文件夹

jillzhang 阅读:58 2024-10-01 17:34:08 评论:0

我需要在一个窗口中使用不同的凭据打开远程服务器上的文件夹 (explorer.exe)。

我设法在没有凭据(我的凭据)的情况下做到了这一点,但是当我使用另一个用户名和另一个密码而不是我的凭据时,它会打开一个提示输入用户名和密码,并显示“访问被拒绝”。

在远程桌面的访问日志中,它说我尝试使用我自己的用户名连接,而不是我输入的其他用户名。所以,这个过程显然是行不通的。

但是,我不明白为什么。我的代码如下:

Dim domain, username, passwordStr, remoteServerName As String 
Dim password As New Security.SecureString 
Dim command As New Process 
 
domain = "domain.com" 
username = "username" 
passwordStr = "password" 
remoteServerName = "serverName" 
 
For Each c As Char In passwordStr.ToCharArray 
    password.AppendChar(c) 
Next 
 
 
command.StartInfo.FileName = "explorer.exe" 
command.StartInfo.Arguments = "\\" & serverName & "\admin$\Temp" 
 
command.StartInfo.UserName = username 
command.StartInfo.Password = password 
command.StartInfo.Domain = domain 
command.StartInfo.Verb = "open" 
command.StartInfo.UseShellExecute = False 
 
command.Start() 

请您参考如下方法:

我在工作中遇到了同样的问题,并且能够通过模拟解决。只需添加一个包含以下内容的新类:

    '***************************************************************************************** 
'***************************************************************************************** 
' Contents: AliasAccount Class 
' 
' This Class is a template class that provides all the functionality to impersonate a user 
' over a designated instance. 
'***************************************************************************************** 
'***************************************************************************************** 
 
 
Public Class AliasAccount 
  Private _username, _password, _domainname As String 
 
  Private _tokenHandle As New IntPtr(0) 
  Private _dupeTokenHandle As New IntPtr(0) 
  Private _impersonatedUser As System.Security.Principal.WindowsImpersonationContext 
 
 
  Public Sub New(ByVal username As String, ByVal password As String) 
    Dim nameparts() As String = username.Split("\") 
    If nameparts.Length > 1 Then 
      _domainname = nameparts(0) 
      _username = nameparts(1) 
    Else 
      _username = username 
    End If 
    _password = password 
  End Sub 
 
  Public Sub New(ByVal username As String, ByVal password As String, ByVal domainname As String) 
    _username = username 
    _password = password 
    _domainname = domainname 
  End Sub 
 
 
  Public Sub BeginImpersonation() 
    'Const LOGON32_PROVIDER_DEFAULT As Integer = 0 
    'Const LOGON32_LOGON_INTERACTIVE As Integer = 2 
    Const LOGON32_LOGON_NEW_CREDENTIALS As Integer = 9 
    Const LOGON32_PROVIDER_WINNT50 As Integer = 3 
    Const SecurityImpersonation As Integer = 2 
 
    Dim win32ErrorNumber As Integer 
 
    _tokenHandle = IntPtr.Zero 
    _dupeTokenHandle = IntPtr.Zero 
 
    If Not LogonUser(_username, _domainname, _password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, _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() 
  End Sub 
 
 
  Public Sub EndImpersonation() 
    If Not _impersonatedUser Is Nothing Then 
      _impersonatedUser.Undo() 
      _impersonatedUser = Nothing 
 
      If Not System.IntPtr.op_Equality(_tokenHandle, IntPtr.Zero) Then 
        CloseHandle(_tokenHandle) 
      End If 
      If Not System.IntPtr.op_Equality(_dupeTokenHandle, IntPtr.Zero) Then 
        CloseHandle(_dupeTokenHandle) 
      End If 
    End If 
  End Sub 
 
 
  Public ReadOnly Property username() As String 
    Get 
      Return _username 
    End Get 
  End Property 
 
  Public ReadOnly Property domainname() As String 
    Get 
      Return _domainname 
    End Get 
  End Property 
 
 
  Public ReadOnly Property currentWindowsUsername() As String 
    Get 
      Return System.Security.Principal.WindowsIdentity.GetCurrent().Name 
    End Get 
  End Property 
 
 
#Region "Exception Class" 
  Public Class ImpersonationException 
    Inherits System.Exception 
 
    Public ReadOnly win32ErrorNumber As Integer 
 
    Public Sub New(ByVal win32ErrorNumber As Integer, ByVal msg As String, ByVal username As String, ByVal domainname As String) 
      MyBase.New(String.Format("Impersonation of {1}\{0} failed! [{2}] {3}", username, domainname, win32ErrorNumber, msg)) 
      Me.win32ErrorNumber = win32ErrorNumber 
    End Sub 
  End Class 
#End Region 
 
 
#Region "External Declarations and Helpers" 
  Private Declare Auto Function LogonUser Lib "advapi32.dll" (ByVal lpszUsername As [String], _ 
          ByVal lpszDomain As [String], ByVal lpszPassword As [String], _ 
          ByVal dwLogonType As Integer, ByVal dwLogonProvider As Integer, _ 
          ByRef phToken As IntPtr) As Boolean 
 
 
  Private Declare Auto Function DuplicateToken Lib "advapi32.dll" (ByVal ExistingTokenHandle As IntPtr, _ 
              ByVal SECURITY_IMPERSONATION_LEVEL As Integer, _ 
              ByRef DuplicateTokenHandle As IntPtr) As Boolean 
 
 
  Private Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Boolean 
 
 
  <System.Runtime.InteropServices.DllImport("kernel32.dll")> _ 
  Private Shared Function FormatMessage(ByVal dwFlags As Integer, ByRef lpSource As IntPtr, _ 
          ByVal dwMessageId As Integer, ByVal dwLanguageId As Integer, ByRef lpBuffer As [String], _ 
          ByVal nSize As Integer, ByRef Arguments As IntPtr) As Integer 
  End Function 
 
 
  Private Function GetErrorMessage(ByVal errorCode As Integer) As String 
    Dim FORMAT_MESSAGE_ALLOCATE_BUFFER As Integer = &H100 
    Dim FORMAT_MESSAGE_IGNORE_INSERTS As Integer = &H200 
    Dim FORMAT_MESSAGE_FROM_SYSTEM As Integer = &H1000 
 
    Dim messageSize As Integer = 255 
    Dim lpMsgBuf As String = "" 
    Dim dwFlags As Integer = FORMAT_MESSAGE_ALLOCATE_BUFFER Or FORMAT_MESSAGE_FROM_SYSTEM Or FORMAT_MESSAGE_IGNORE_INSERTS 
 
    Dim ptrlpSource As IntPtr = IntPtr.Zero 
    Dim prtArguments As IntPtr = IntPtr.Zero 
 
    Dim retVal As Integer = FormatMessage(dwFlags, ptrlpSource, errorCode, 0, lpMsgBuf, messageSize, prtArguments) 
    If 0 = retVal Then 
      Throw New System.Exception("Failed to format message for error code " + errorCode.ToString() + ". ") 
    End If 
 
    Return lpMsgBuf 
  End Function 
 
#End Region 
 
End Class 

这将允许您模拟指定用户进行 session 。所以你会比改变你的代码:

Dim domain, username, passwordStr, remoteServerName As String     
Dim password As New Security.SecureString     
Dim command As New Process   
 
domain = "domain.com"     
username = "username"     
passwordStr = "password"     
remoteServerName = "serverName" 
Dim impersonator As New AliasAccount(username, password) 
 
For Each c As Char In passwordStr.ToCharArray         
  password.AppendChar(c)     
Next 
 
 
command.StartInfo.FileName = "explorer.exe"     
command.StartInfo.Arguments = "\\" & serverName & "\admin$\Temp"         
 
command.StartInfo.UserName = username     
command.StartInfo.Password = password     
command.StartInfo.Domain = domain     
command.StartInfo.Verb = "open"     
command.StartInfo.UseShellExecute = False  
 
  impersonator.BeginImpersonation() 
command.Start()  
  impersonator.EndImpersonation() 


标签:程序员
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号