无法使用Impersonate以管理员身份连接到服务器

时间:2016-05-16 14:53:24

标签: vb.net vb.net-2010 impersonation

我必须以管理员身份冒充查看某些网络文件夹,但由于应用程序识别当前记录的帐户,因此无法正常工作。这是我在互联网上找到的课程:

Public Class Impersonator
Private _username As String
Private _password As String
Private _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(Convert.ToChar("\"))
    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 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



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 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

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

结束课程 结束班

2 个答案:

答案 0 :(得分:0)

您是否真的尝试访问网络资源,或者您是否仅确定它无法使用:WindowsIdentity.GetCurrent.Name结果?

它的工作方式:

使用默认提供程序进行交互式登录只有在用户可以实际连接到服务器时才能正常工作。在较旧的Windows版本中,这不是强制执行的,可以用来代替下面的版本。

Logon_New_Credential(使用Winnt50提供程序)将模拟用户进行远程连接,但会在本地使用原始用户

Logon_Network(使用Winnt50驱动程序)将在本地模拟您作为所需用户,但如果您尝试远程启动连接,则令牌将失败。

因此,如果您在模拟循环中尝试使用WindowsIdentity.GetCurrent.Name,Logon_New_Credential将返回原始用户,但在访问网络资源时将使用模拟用户。

见下文

Different authentication test

答案 1 :(得分:0)

非常感谢Sage Pourpre,如果我使用第一个选项,它会起作用:

LOGON32_PROVIDER_DEFAULT | LOGON32_LOGON_INTERACTIVE

目前我使用这种类型的登录,但我会记录文件,因为我想了解这些差异。