2008-11-03 17 views
20

En C#, ¿cómo configuro la identidad de un subproceso?Establecer identidad de subproceso

Por ejemplo, si tengo Thread MyThread, que ya está iniciado, ¿puedo cambiar la identidad de MyThread?

¿O no es esto posible?

Respuesta

27

Puede establecer la Identidad de un hilo creando un nuevo Principal. Puede usar cualquier Identidad que herede de System.Security.Principal.IIdentity, pero necesita una clase que hereda de System.Security.Principal.IPrincipal que toma el tipo de identidad que está utilizando.
Para simplificar el marco .NET proporciona GenericPrincipal y GenericIdentity clases que se pueden utilizar como esto:

using System.Security.Principal; 

// ... 
GenericIdentity identity = new GenericIdentity("M.Brown"); 
identity.IsAuthenticated = true; 

// ... 
System.Threading.Thread.CurrentPrincipal = 
    new GenericPrincipal(
     identity, 
     new string[] { "Role1", "Roll2" } 
    ); 

//... 
if (!System.Threading.Thread.CurrentPrincipal.IsInRole("Roll1")) 
{ 
     Console.WriteLine("Permission denied"); 
     return; 
} 

sin embargo esto no le otorgan derechos ventanas a la materia utilizando la nueva identidad. Pero puede ser útil si está desarrollando un sitio web y desea crear su propia administración de usuarios.

Si desea fingir ser un usuario de Windows diferente a la cuenta que está utilizando en ese momento, debe usar la suplantación. Se puede encontrar un ejemplo de cómo hacer esto en la Ayuda para System.Security.Principal.WindowsIdentity.Impersonate(). Existen limitaciones sobre las cuentas con las que se puede suplantar la cuenta bajo la que se está ejecutando.

En algunos casos, el .Net framework hace suplantación para usted. Un ejemplo de dónde ocurre esto es si está desarrollando un sitio web ASP.Net y tiene la Autenticación integrada de Windows activada para el directorio virtual o sitio en el que se está ejecutando.

+0

Si usa ['GenericIdentity Constructor (String, String)'] (http: // msdn. microsoft.com/en-us/library/2wh03ckb(v=vs.110).aspx) puede omitir el bit 'IsAuthenticated = true'. –

+0

Estoy usando .NET 4.5, y no puedo compilar esta declaración identity.IsAuthenticated = true; porque la propiedad "IsAuthenticated" solo tiene acceso de acceso, puede por favor, hacer una actualización para el código en el cual se usa el framework .NET 4.5.gracias de todos modos, su código me fue ayudado, (con algunas modificaciones) –

+1

Modifiqué su código en .NET 4.5 como el siguiente para que funcione GenericIdentity identity = new GenericIdentity ("user1", "Forms"); Thread.CurrentPrincipal = new GenericPrincipal (identidad, nueva cadena [] {"role1"}); puede usar este código para actualizar su publicación útil, gracias de nuevo. –

3

Sí, utilizando impersonation literalmente

using (new Impersonation()) 
{ 
    // your elevated code 
} 

y la clase es el siguiente, para la configuración de uso castillo adaptador de diccionario si parece extraño.

[PermissionSet(SecurityAction.Demand, Name = "FullTrust")] 
public class Impersonation : IDisposable 
{ 
    private readonly SafeTokenHandle _handle; 
    private readonly WindowsImpersonationContext _context; 

    //const int Logon32LogonNewCredentials = 9; 
    private const int Logon32LogonInteractive = 2; 

    public Impersonation() 
    { 
     var settings = Settings.Instance.Whatever; 
     var domain = settings.Domain; 
     var username = settings.User; 
     var password = settings.Password; 
     var ok = LogonUser(username, domain, password, Logon32LogonInteractive, 0, out _handle); 
     if (!ok) 
     { 
      var errorCode = Marshal.GetLastWin32Error(); 
      throw new ApplicationException(string.Format("Could not impersonate the elevated user. LogonUser returned error code {0}.", errorCode)); 
     } 
     _context = WindowsIdentity.Impersonate(_handle.DangerousGetHandle()); 
    } 

    public void Dispose() 
    { 
     _context.Dispose(); 
     _handle.Dispose(); 
    } 

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
    private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken); 

    public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid 
    { 
     private SafeTokenHandle() 
      : base(true) 
     { } 

     [DllImport("kernel32.dll")] 
     [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
     [SuppressUnmanagedCodeSecurity] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     private static extern bool CloseHandle(IntPtr handle); 

     protected override bool ReleaseHandle() 
     { 
      return CloseHandle(handle); 
     } 
    } 
} 
+0

¿Puedes elaborar? Si MyThread ya se estaba ejecutando, ¿podemos cambiar su CurrentPrincipal? – Duncan

+0

sí, ¿siguió el enlace? hay ejemplos allí. – dove

+0

Sorprendentemente, este enlace me ayudó a resolver mi problema. Si bien no establece la identidad del hilo, le permite ejecutar el código mientras se hace pasar por otro usuario. Al examinar el primer ejemplo en el enlace hice una copia de la identidad del usuario actual en mi hilo principal usando: var newId = WindowsIdentity.GetCurrent(); Después pasé esta identidad a mis hilos y suplanté al usuario con esta cláusula: using (var impersonationContext = newId.Impersonate()) El código ejecutado dentro del uso se ejecutará bajo la identidad personificada. – Sal

3

Esta es una actualización de la respuesta aceptada [ aplicar en .NET framework 4.5 y superior]
En .NET 4.5 la propiedad IsAuthenticated no tiene un acceso de conjunto, por lo que no puede establecerlo directamente como la respuesta aceptada.
Puede usar el siguiente código para establecer esa propiedad.

GenericIdentity identity = new GenericIdentity("someuser", "Forms"); 
Thread.CurrentPrincipal = new GenericPrincipal(identity, new string[] { "somerole" }); 
Cuestiones relacionadas