仅在模拟类库(dll)

时间:2015-10-15 21:56:20

标签: asp.net .net vb.net dll impersonation

我们有一个类库,其中包含我们在多个网络应用中使用的一些常用方法,我们的Impersonation课程出现了问题。在每个应用程序中使用LogonUser模拟时,Environment.UserName将返回正在使用该应用程序的用户。但是当我们在类库中使用块来模拟它时,它将作为AppPool标识返回。

返回客户的用户名:

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

If (LogonUser(Config.AdminUser, Config.AdminDomain, Config.AdminPassword, 9, 0, token) <> 0) Then
    Dim newIdentity As WindowsIdentity = New WindowsIdentity(token)
    Using impersonatedUser As WindowsImpersonationContext = newIdentity.Impersonate()
        name = Environment.UserName
    End Using
End If

返回app pool用户名:

Imports Class.Library    

Using admin As New Impersonation
    name = Environment.UserName
End Using

HttpContext.Current.User.Identity.Name似乎返回了我们正在寻找的用户名,但我们无法看到为什么Environment.UserName在服务器上有效运行,但只有在它没有使用我们的自定义类库时才会有效#39} ; s dll参考。以下是我们的模拟课程:

Public Class Impersonation : Implements IDisposable
    Private impersonationContext As WindowsImpersonationContext = Nothing

    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 Integer
    Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Boolean
    Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Boolean
    Declare Auto Function DuplicateToken Lib "advapi32.dll" (ByVal hToken As IntPtr, ByVal impersonationLevel As Integer, ByRef hNewToken As IntPtr) As Integer

    Private Shared newIdentity As WindowsIdentity
    Private Shared token As New IntPtr(0)

    Public Sub New(Optional ByVal userName As String = "", Optional ByVal password As String = "", Optional ByVal domainName As String = Config.AdminDomain)
        If userName = "" Then
            userName = Config.AdminUser
        End If

        If password = "" Then
            password = Config.AdminPassword
        End If

        Dim logonType As Integer = 9 
        impersonationContext = ImpersonateUser(userName, domainName, password, logonType)
    End Sub

    Private Sub Undo()
        If impersonationContext IsNot Nothing Then
            impersonationContext.Undo()
        End If
    End Sub

    Private Shared Function ImpersonateUser(ByVal userName As String, ByVal domain As String, ByVal password As String, ByVal logonType As Integer) As WindowsImpersonationContext
        Dim res As WindowsImpersonationContext = Nothing
        Dim tempWindowsIdentity As WindowsIdentity = Nothing
        Dim token As IntPtr = IntPtr.Zero
        Dim tokenDuplicate As IntPtr = IntPtr.Zero
        Try
            If (RevertToSelf()) Then
                If LogonUser(userName, domain, password, logonType, 0, token) Then
                    If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then
                        tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)
                        Return tempWindowsIdentity.Impersonate()
                    Else
                        Throw New Win32Exception(Marshal.GetLastWin32Error())
                    End If
                Else
                    Throw New Win32Exception(Marshal.GetLastWin32Error())
                End If
            Else
                Throw New Win32Exception(Marshal.GetLastWin32Error())
            End If
        Finally
            If token <> IntPtr.Zero Then
                CloseHandle(token)
            End If
            If tokenDuplicate <> IntPtr.Zero Then
                CloseHandle(tokenDuplicate)
            End If
        End Try
        Return res
    End Function

    Private disposedValue As Boolean = False        

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            Undo()
        End If
        Me.disposedValue = True
    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub

End Class

我觉得它与服务器上的dll文件有关,当我们使用using块时,Environment.UserName获取进程在服务器上运行的用户名。但是我无法理解为什么最初在使用模拟的方法中创建New WindowsIdentity()而不是从我们的dll引用它时,因为它们都在服务器上运行。

基本上,当我们在本地运行并尝试调试出现的问题时,HttpContext.Current.User.Identity.Name已成为我们的问题。我们希望,1。为了知识目的而发生这种情况的答案,以及2.如果他们的偶数超出HttpContext.Current.User.Identity.Name,则可能的解决方案。 (欢迎使用VB或C#中的答案。)

1 个答案:

答案 0 :(得分:0)

我通过在类库中创建一个新方法解决了我的问题:

Public Shared Function Current() As String
    If Not HttpContext.Current.Request.IsLocal Then
        Dim id As String = HttpContext.Current.User.Identity.Name
        Return id.Substring(4)
    Else
        Return Environment.UserName
    End If
End Function

如果代码在服务器上运行,则使用HttpContext来提取域\用户名。然后我将域名包含在内(我们的域名只有三个字符)。

如果是在本地运行,我会返回Environment.UserName 我只是通过引用类和方法(Employees.Current

在我的Web应用程序中调用此字符串