Domanda

Soluzione (kinda):

Si scopre che questa rappresentazione della sicurezza di .NET consente solo l'accesso a livello di applicazione. Poiché l'oggetto COM è a livello di sistema, l'utente impersonato non può ancora istanziarlo. L'ho capito facendo clic con il pulsante destro del mouse sull'eseguibile e selezionando " Esegui come ... " ;, il programma ha funzionato bene. Ho scoperto che avvia il programma con accesso al sistema (supponendo che l'utente con cui lo stai eseguendo abbia tali credenziali). Ora sto creando un programma esterno che avvierà questa applicazione usando questo metodo.

Grazie per i suggerimenti: D


Ho un'installazione di Windows XP su una macchina virtuale. Fa parte del mio dominio, ma l'utente che ha effettuato l'accesso è solo un utente locale. Ovviamente, se provo ad accedere a una condivisione di rete, verrà richiesto un utente / password:

 alt text

Il programma che sto testando sulla macchina virtuale utilizza un oggetto COM per interfacciarsi con i dati di un altro programma. Se non impersono, ricevo errori perché non ho le credenziali appropriate.

Ho fatto qualche ricerca sulla questione e ho trovato un numero di siti Web che contenevano una discreta quantità di informazioni su VB.NET. Il problema che sto riscontrando con il codice che ho scritto è che posso accedere alle risorse di rete, ma non posso creare un'istanza dell'oggetto COM.

Se compilo e invio il prompt delle credenziali (sopra) prima di provare a crearne un'istanza, funziona perfettamente. Questo mi porta a credere che ci debba essere qualcosa che il prompt delle credenziali di WinXP sta facendo, ma non lo sono. Di seguito è riportato il codice che sto usando per la rappresentazione:

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

Ho anche provato a inviare diversi flag al metodo imitatore, ma nulla sembra funzionare. Ecco le diverse bandiere che ho trovato:

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
È stato utile?

Soluzione

Mi sono imbattuto in questo in precedenza e ho usato due diversi assoli: il più semplice era usare un'app di terze parti: TqcRunas: http://www.quimeras.com/Products/products.asp che consente di impacchettare le credenziali richieste in un file crittografato. Tuttavia è un problema se la password è forzata a scadere.

L'altra soluzione che ho usato è quella di chiamare un nuovo processo con credenziali alternative:

        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

Altri suggerimenti

Con le tue definizioni, io uso

LogonUser(_username, _domainname, _password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, _tokenHandle)

nel mio codice che si sta autenticando attraverso la rete. Sto impersonando un utente locale sulla scatola remota, come te. È stato tanto tempo fa che non ricordo la logica per l'utilizzo di questi valori.

Faccio una cosa simile per mappare le unità di rete per copiare file tra macchine. Non ho scritto il codice ma è praticamente uguale al tuo, tranne due cose:

  • Dopo che il metodo Impersonate ritorna chiudo entrambi i token usando la routine CloseHandle, prima di uscire dal mio metodo di rappresentazione.

  • Nella parte superiore dell'imitatore la prima cosa che succede è una chiamata a RevertToSelf, presumibilmente per annullare qualsiasi imitazione precedente.

Non so se farebbero la differenza, ma vale la pena provare. Ecco le dichiarazioni pertinenti:

Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long
Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top