Après le saut à travers plusieurs posts sur ce sujet, je suis arrivé finalement à une classe simple pour encapsuler l'ensemble de l'usurpation de l'identité de la logique. Il vous permet de faire un simple appel comme ceci:
using (new Impersonation(domain, username, password))
{
// do whatever you want
}
Ajouter cette classe à votre projet, et vous allez loin:
using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using Microsoft.Win32.SafeHandles;
namespace MyApplication
{
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public class Impersonation : IDisposable
{
private readonly SafeTokenHandle _handle;
private readonly WindowsImpersonationContext _context;
const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
public Impersonation(string domain, string username, string password)
{
var ok = LogonUser(username, domain, password,
LOGON32_LOGON_NEW_CREDENTIALS, 0, out this._handle);
if (!ok)
{
var errorCode = Marshal.GetLastWin32Error();
throw new ApplicationException(string.Format("Could not impersonate the elevated user. LogonUser returned error code {0}.", errorCode));
}
this._context = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle());
}
public void Dispose()
{
this._context.Dispose();
this._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);
}
}
}
}
Notez que je suis en utilisant le type de connexion 9 (nouveau les informations d'identification). Dans mon cas, j'ai besoin de vous connecter via de sécurité de confiance à un serveur sql server avec une connexion différente, de sorte que ce qui fonctionne le mieux. Vous pouvez avoir besoin d'un positions type d'ouverture de session en fonction de vos objectifs. Jetez un oeil à ce site pour d'autres types de connexion.
Mise à JOUR
Basé sur la poursuite de la rétroaction positive, j'ai décidé de nettoyer légèrement vers le haut et l'héberger dans une bibliothèque pour faciliter la consommation. Source et docs sur GitHub, prêt à l'emploi sur NuGet. Profitez-en!