Une fois, j'ai réussi à créer un lot de comptes de domaine avec des boîtes aux lettres à l'aide d'un programme Windows. Cependant, lorsque j'ai donné ce code à une de mes collègues (elle était responsable du développement d'applications Web) et que je l'ai migré vers asp.net, il n'a pu que créer un domaine. compte, impossible de créer une boîte aux lettres. Pourquoi?
Nous avons consulté un ingénieur Microsoft et il nous a dit que cela était dû à des autorisations insuffisantes sur asp.net. Nous devrions simuler l'utilisateur dans asp.net afin qu'il puisse être créé avec succès.
J'ai extrait des articles pertinents de Microsoft :
Emprunter l'identité d'un compte ou d'un utilisateur authentifié IIS
Pour usurper l'identité d'un utilisateur authentifié Microsoft Internet Information Services (IIS) lorsque chaque demande est reçue pour chaque page d'une application ASP.NET, vous devez inclure dans le fichier Web.config de cette application la balise <identity> et définissez l'attribut d'emprunt d'identité sur true. Par exemple :
<identity impersonate="true" />
Emprunter l'identité d'un utilisateur spécifique pour toutes les demandes adressées à une application ASP.NET
Pour emprunter l'identité d'un utilisateur spécifique pour toutes les demandes sur toutes les pages d'une application ASP.NET, vous pouvez spécifier l'attribut userName et password. Par exemple :
<identity impersonate="true" userName="accountname" password="password" />
Remarque : L'identité du processus qui emprunte l'identité d'un utilisateur spécifique sur un thread doit disposer de l'autorisation « Dans le cadre du système d'exploitation ». Par défaut, le processus Aspnet_wp.exe s'exécute sous un compte d'ordinateur nommé ASPNET. Cependant, ce compte ne dispose pas des autorisations nécessaires pour usurper l'identité d'un utilisateur spécifique. Si vous essayez d'usurper l'identité d'un utilisateur spécifique, un message d'erreur apparaîtra.
Pour résoudre ce problème, utilisez une des méthodes suivantes :
?
Accordez au compte ASPNET (le compte le moins privilégié) l'autorisation « Agir en tant que partie du système d'exploitation ».
Remarque : Bien que cette méthode puisse résoudre le problème, Microsoft ne la recommande pas.
•
Dans la section de configuration <processModel> du fichier Machine.config, remplacez le compte sous lequel le processus Aspnet_wp.exe s'exécute par le compte Système.
Usurper l'identité d'un utilisateur authentifié dans le code
Pour emprunter l'identité d'un utilisateur authentifié (User.Identity) uniquement lors de l'exécution d'une partie spécifique du code, vous pouvez utiliser le code suivant. Cette méthode nécessite que l’ID utilisateur d’authentification soit de type WindowsIdentity.
Visual Basic .NET
Dim impersonationContext As System.Security.Principal.WindowsImpersonationContext
Atténuer currentWindowsIdentity en tant que System.Security.Principal.WindowsIdentity
currentWindowsIdentity = CType (User.Identity, System.Security.Principal.WindowsIdentity)
impersonationContext = currentWindowsIdentity.Impersonate()
'Insérez ici votre code qui s'exécute dans le contexte de sécurité de l'utilisateur authentifiant.
impersonationContext.Undo()
Visual C# .NET
System.Security.Principal.WindowsImpersonationContext impersonationContext;
emprunt d'identitéContext =
((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
//Insérez ici votre code qui s'exécute dans le contexte de sécurité de l'utilisateur authentifiant.
impersonationContext.Undo();
Visual J# .NET
System.Security.Principal.WindowsImpersonationContext impersonationContext;
emprunt d'identitéContext =
((System.Security.Principal.WindowsIdentity)get_User().get_Identity()).Impersonate();
//Insérez ici votre code qui s'exécute dans le contexte de sécurité de l'utilisateur authentifiant.
impersonationContext.Undo();
Usurper l'identité d'un utilisateur spécifique dans le code
Pour emprunter l'identité d'un utilisateur spécifique uniquement lors de l'exécution de parties spécifiques de votre code, utilisez le code suivant :
Visual Basic .NET
<%@ Page Language="VB" %>
<%@ Importer l'espace de noms = "System.Web" %>
<%@ Importer l'espace de noms = "System.Web.Security" %>
<%@ Importer l'espace de noms = "System.Security.Principal" %>
<%@ Importer l'espace de noms = "System.Runtime.InteropServices" %>
<script runat=serveur>
Dim LOGON32_LOGON_INTERACTIVE Comme entier = 2
Dim LOGON32_PROVIDER_DEFAULT Comme entier = 0
Atténuer le contexte d'emprunt d'identité en tant que WindowsImpersonationContext
Déclarez la fonction LogonUserA 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
Déclarez la fonction automatique DuplicateToken Lib "advapi32.dll" ( _
ByVal ExistingTokenHandle As IntPtr, _
ByVal ImpersonationLevel As Integer, _
ByRef DuplicateTokenHandle As IntPtr) As Integer
Déclarer la fonction automatique RevertToSelf Lib "advapi32.dll" () aussi longtemps
Déclarez la fonction automatique CloseHandle Lib "kernel32.dll" (handle ByVal comme IntPtr) aussi longtemps
Public Sub Page_Load (ByVal s As Object, ByVal e As EventArgs)
Si impersonateValidUser("username", "domain", "password") Alors
'Insérez ici votre code qui s'exécute dans le contexte de sécurité d'un utilisateur spécifique.
annulerImpersonation()
Autre
« Votre usurpation d'identité a échoué. Par conséquent, incluez ici un mécanisme de sécurité.
Fin si
Fin du sous-marin
Fonction privée impersonateValidUser (ByVal userName As String, _
Domaine ByVal sous forme de chaîne, mot de passe ByVal sous forme de chaîne) sous forme booléenne
Dim tempWindowsIdentity As WindowsIdentity
Jeton Dim As IntPtr = IntPtr.Zero
Dim tokenDuplicate As IntPtr = IntPtr.Zero
impersonateValidUser = Faux
Si RevertToSelf() Alors
Si LogonUserA(userName, domaine, mot de passe, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, jeton) <> 0 Puis
Si DuplicateToken(token, 2, tokenDuplicate) <> 0 Alors
tempWindowsIdentity = Nouvelle identité Windows (tokenDuplicate)
impersonationContext = tempWindowsIdentity.Impersonate()
Si ce n'est pas le cas, le contexte d'emprunt d'identité n'est rien, alors
impersonateValidUser = Vrai
Fin si
Fin si
Fin si
Fin si
Si ce n'est pas le cas tokenDuplicate.Equals(IntPtr.Zero) Alors
CloseHandle (jetonDuplicate)
Fin si
Si ce n'est pas le cas token.Equals(IntPtr.Zero) Alors
CloseHandle (jeton)
Fin si
Fonction de fin
Sous-privé undoImpersonation()
impersonationContext.Undo()
Fin du sous-marin
</script>
Visual C# .NET
<%@ Page Language="C#"%>
<%@ Importer l'espace de noms = "System.Web" %>
<%@ Importer l'espace de noms = "System.Web.Security" %>
<%@ Importer l'espace de noms = "System.Security.Principal" %>
<%@ Importer l'espace de noms = "System.Runtime.InteropServices" %>
<script runat=serveur>
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext impersonationContext;
[DllImport("advapi32.dll")]
public static extern int LogonUserA (String lpszUserName,
Chaîne lpszDomain,
Chaîne lpszPassword,
int dwLogonType,
int dwLogonProvider,
réf IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int DuplicateToken(IntPtr hToken,
int niveau d'emprunt d'identité,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern bool CloseHandle (descripteur IntPtr);
public void Page_Load (Object s, EventArgs e)
{
if(impersonateValidUser("nom d'utilisateur", "domaine", "mot de passe"))
{
//Insérez ici votre code qui s'exécute dans le contexte de sécurité d'un utilisateur spécifique.
annulerImpersonation();
}
autre
{
//Votre emprunt d'identité a échoué. Par conséquent, incluez ici un mécanisme de sécurité.
}
}
private bool impersonateValidUser (String userName, String domain, String password)
{
WindowsIdentity tempWindowsIdentity ;
Jeton IntPtr = IntPtr.Zero ;
IntPtr tokenDuplicate = IntPtr.Zero ;
si (RevertToSelf ())
{
if(LogonUserA(nom d'utilisateur, domaine, mot de passe, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, jeton de référence) != 0)
{
if(DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
si (emprunt d'identitéContext != null)
{
CloseHandle(jeton);
CloseHandle(tokenDuplicate);
renvoie vrai ;
}
}
}
}
si (jeton! = IntPtr.Zero)
CloseHandle(jeton);
si(tokenDuplicate!=IntPtr.Zero)
CloseHandle(tokenDuplicate);
renvoie faux ;
}
privé vide annulerImpersonation()
{
impersonationContext.Undo();
}
</script>
Visual J# .NET
<%@ Page Language="VJ#" %>
<%@ Importer l'espace de noms="System.Web" %>
<%@ Import Namespace="System.Web.Security" %>
<%@ Import Namespace="System.Security.Principal" %>
<%@ Import Namespace="System.Runtime.InteropServices" %>
<script runat=serveur>
public statique int LOGON32_LOGON_INTERACTIVE = 2;
public statique int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext impersonationContext;
/** @attribute DllImport("advapi32.dll") */
public static native int LogonUserA (String lpszUserName,
Chaîne lpszDomain,
Chaîne lpszPassword,
int dwLogonType,
int dwLogonProvider,
System.IntPtr[] phToken);
/** @attribute DllImport("advapi32.dll",
CharSet=CharSet.Auto, SetLastError=true) */
public static native int DuplicateToken (System.IntPtr hToken,
int niveau d'emprunt d'identité,
System.IntPtr[] hNewToken);
/** @attribute DllImport("kernel32.dll",CharSet=CharSet.Auto) */
public statique natif booléen CloseHandle(System.IntPtr[] handle);
/** @attribute DllImport("advapi32.dll",
CharSet=CharSet.Auto,SetLastError=true) */
public statique natif booléen RevertToSelf();
public void Page_Load (Object s, System.EventArgs e)
{
if(impersonateValidUser("nom d'utilisateur", "domaine", "mot de passe"))
{
//Insérez ici votre code qui s'exécute dans le contexte de sécurité d'un utilisateur spécifique.
annulerImpersonation();
}
autre
{
//Votre emprunt d'identité a échoué. Par conséquent, incluez ici un mécanisme de sécurité.
}
}
emprunt d'identité booléen privéValidUser (String userName, String domain, String password)
{
WindowsIdentity tempWindowsIdentity ;
Jeton System.IntPtr[] = nouveau System.IntPtr[1] ;
System.IntPtr[] tokenDuplicate = new System.IntPtr[1];
si (RevertToSelf ())
{
if(LogonUserA(nom d'utilisateur, domaine, mot de passe, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, jeton) != 0)
{
if(DuplicateToken(token[0], 2, tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate[0]);
impersonationContext = tempWindowsIdentity.Impersonate();
si (emprunt d'identitéContext != null)
{
CloseHandle(tokenDuplicate);
CloseHandle(jeton);
renvoie vrai ;
}
}
}
}
if(!token[0].Equals(System.IntPtr.Zero))
CloseHandle(jeton);
if(!tokenDuplicate[0].Equals(System.IntPtr.Zero))
CloseHandle(tokenDuplicate);
renvoie faux ;
}
privé vide annulerImpersonation()
{
impersonationContext.Undo();
}
</script>
Remarque : L'identité du processus qui emprunte l'identité d'un utilisateur spécifique sur un thread doit disposer de l'autorisation « Dans le cadre du système d'exploitation ». Par défaut, le processus Aspnet_wp.exe s'exécute sous un compte d'ordinateur nommé ASPNET. Cependant, ce compte ne dispose pas des autorisations nécessaires pour usurper l'identité d'un utilisateur spécifique. Si vous essayez d'usurper l'identité d'un utilisateur spécifique, un message d'erreur apparaîtra.
Pour résoudre ce problème, utilisez une des méthodes suivantes :
?
Accordez au compte ASPNET l'autorisation « Agir en tant que partie du système d'exploitation ».
•
Dans la section de configuration <processModel> du fichier Machine.config, remplacez le compte sous lequel le processus Aspnet_wp.exe s'exécute par le compte Système.