Ich habe einmal mit einem Windows-Programm erfolgreich eine Reihe von Domänenkonten mit Postfächern erstellt. Als ich diesen Code jedoch einer meiner Kollegen gab (sie war für die Entwicklung von Webanwendungen verantwortlich) und ihn auf asp.net migrierte, konnte er nur eine Domäne erstellen Konto, Postfach kann nicht erstellt werden. Warum?
Wir haben einen Microsoft-Ingenieur konsultiert und er hat uns mitgeteilt, dass dies auf unzureichende Berechtigungen von asp.net zurückzuführen ist. Wir sollten den Benutzer in asp.net simulieren, damit er erfolgreich erstellt werden kann.
Ich habe relevante Artikel von Microsoft extrahiert:
Imitieren eines IIS-authentifizierten Kontos oder Benutzers
Um sich als ein von Microsoft Internet Information Services (IIS) authentifizierter Benutzer auszugeben, wenn jede Anforderung für jede Seite in einer ASP.NET-Anwendung empfangen wird, müssen Sie in die Web.config-Datei für diese Anwendung das Tag <identity> aufnehmen und setzen Sie das Attribut „impersonate“ auf „true“. Beispiel:
<identity impersonate="true" />
Imitieren eines bestimmten Benutzers für alle Anforderungen an eine ASP.NET-Anwendung
Um die Identität eines bestimmten Benutzers für alle Anforderungen auf allen Seiten einer ASP.NET-Anwendung anzunehmen, können Sie das Attribut „userName“ und „password“ angeben. Beispiel:
<identity impersonate="true" userName="accountname" passwort="password" />
Hinweis: Die Identität des Prozesses, der sich als ein bestimmter Benutzer in einem Thread ausgibt, muss über die Berechtigung „Als Teil des Betriebssystems“ verfügen. Standardmäßig wird der Prozess Aspnet_wp.exe unter einem Computerkonto namens ASPNET ausgeführt. Dieses Konto verfügt jedoch nicht über die erforderlichen Berechtigungen, um sich als ein bestimmter Benutzer auszugeben. Wenn Sie versuchen, sich als ein bestimmter Benutzer auszugeben, wird eine Fehlermeldung angezeigt.
Um dieses Problem zu beheben, verwenden Sie eine der folgenden Methoden:
•
Erteilen Sie dem ASPNET-Konto (dem Konto mit den geringsten Privilegien) die Berechtigung „Als Teil des Betriebssystems agieren“.
Hinweis: Obwohl diese Methode das Problem beheben kann, empfiehlt Microsoft diese Methode nicht.
•
Ändern Sie im Konfigurationsabschnitt <processModel> der Datei Machine.config das Konto, unter dem der Prozess Aspnet_wp.exe ausgeführt wird, in das Systemkonto.
Imitieren eines authentifizierten Benutzers im Code
Um sich nur dann als ein authentifizierter Benutzer (User.Identity) auszugeben, wenn ein bestimmter Teil des Codes ausgeführt wird, können Sie den folgenden Code verwenden. Diese Methode erfordert, dass die Authentifizierungsbenutzer-ID vom Typ WindowsIdentity ist.
Visual Basic .NET
Dim impersonationContext als System.Security.Principal.WindowsImpersonationContext
Dimmen Sie currentWindowsIdentity als System.Security.Principal.WindowsIdentity
currentWindowsIdentity = CType(User.Identity, System.Security.Principal.WindowsIdentity)
impersonationContext = currentWindowsIdentity.Impersonate()
'Fügen Sie hier Ihren Code ein, der im Sicherheitskontext des authentifizierenden Benutzers ausgeführt wird.
impersonationContext.Undo()
Visual C# .NET
System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext =
((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
//Fügen Sie hier Ihren Code ein, der im Sicherheitskontext des authentifizierenden Benutzers ausgeführt wird.
impersonationContext.Undo();
Visual J# .NET
System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext =
((System.Security.Principal.WindowsIdentity)get_User().get_Identity()).Impersonate();
//Fügen Sie hier Ihren Code ein, der im Sicherheitskontext des authentifizierenden Benutzers ausgeführt wird.
impersonationContext.Undo();
Imitieren eines bestimmten Benutzers im Code
Um sich nur beim Ausführen bestimmter Teile Ihres Codes als ein bestimmter Benutzer auszugeben, verwenden Sie den folgenden Code:
Visual Basic .NET
<%@ Page Language="VB" %>
<%@ Import Namespace = "System.Web" %>
<%@ Import Namespace = "System.Web.Security" %>
<%@ Import Namespace = "System.Security.Principal" %>
<%@ Import Namespace = "System.Runtime.InteropServices" %>
<script runat=server>
Dimmen Sie LOGON32_LOGON_INTERACTIVE als Ganzzahl = 2
Dimmen Sie LOGON32_PROVIDER_DEFAULT als Ganzzahl = 0
Dimmen Sie impersonationContext als WindowsImpersonationContext
Deklarieren Sie die Funktion LogonUserA Lib „advapi32.dll“ (ByVal lpszUsername As String, _
ByVal lpszDomain als String, _
ByVal lpszPassword As String, _
ByVal dwLogonType As Integer, _
ByVal dwLogonProvider As Integer, _
ByRef phToken As IntPtr) As Integer
Deklarieren Sie die Auto Function DuplicateToken Lib „advapi32.dll“ ( _
ByVal ExistingTokenHandle As IntPtr, _
ByVal ImpersonationLevel As Integer, _
ByRef DuplicateTokenHandle As IntPtr) As Integer
Deklarieren Sie die automatische Funktion RevertToSelf Lib „advapi32.dll“ () als lang
Deklarieren Sie die Auto-Funktion CloseHandle Lib „kernel32.dll“ (ByVal-Handle als IntPtr) als lang
Public Sub Page_Load(ByVal s As Object, ByVal e As EventArgs)
Wenn impersonateValidUser("username", "domain", "password") dann
'Fügen Sie hier Ihren Code ein, der im Sicherheitskontext eines bestimmten Benutzers ausgeführt wird.
undoImpersonation()
Anders
„Ihr Identitätswechsel ist fehlgeschlagen.“
Ende wenn
Sub beenden
Private Funktion impersonateValidUser(ByVal userName As String, _
ByVal-Domäne als String, ByVal-Passwort als String) als boolescher Wert
Dimmen Sie tempWindowsIdentity als WindowsIdentity
Dimm-Token als IntPtr = IntPtr.Zero
Dimm tokenDuplicate As IntPtr = IntPtr.Zero
impersonateValidUser = Falsch
Wenn RevertToSelf() dann
Wenn LogonUserA(Benutzername, Domäne, Passwort, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, Token) <> 0 Dann
Wenn DuplicateToken(token, 2, tokenDuplicate) <> 0, dann
tempWindowsIdentity = Neue WindowsIdentity(tokenDuplicate)
impersonationContext = tempWindowsIdentity.Impersonate()
Wenn nicht, dann ist impersonationContext nichts
impersonateValidUser = True
Ende wenn
Ende wenn
Ende wenn
Ende wenn
Wenn nicht tokenDuplicate.Equals(IntPtr.Zero) Dann
CloseHandle(tokenDuplicate)
Ende wenn
Wenn nicht token.Equals(IntPtr.Zero) Dann
CloseHandle(Token)
Ende wenn
Funktion beenden
Private Sub undoImpersonation()
impersonationContext.Undo()
Sub beenden
</script>
Visual C# .NET
<%@ Page Language="C#"%>
<%@ Import Namespace = "System.Web" %>
<%@ Import Namespace = "System.Web.Security" %>
<%@ Import Namespace = "System.Security.Principal" %>
<%@ Import Namespace = "System.Runtime.InteropServices" %>
<script runat=server>
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,
Zeichenfolge lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
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(IntPtr handle);
public void Page_Load(Object s, EventArgs e)
{
if(impersonateValidUser("Benutzername", "Domäne", "Passwort"))
{
//Fügen Sie hier Ihren Code ein, der im Sicherheitskontext eines bestimmten Benutzers ausgeführt wird.
undoImpersonation();
}
anders
{
//Ihr Identitätswechsel ist fehlgeschlagen. Fügen Sie daher hier einen ausfallsicheren Mechanismus ein.
}
}
private bool impersonateValidUser(String Benutzername, String Domäne, String Passwort)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if(RevertToSelf())
{
if(LogonUserA(Benutzername, Domäne, Passwort, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, Ref-Token) != 0)
{
if(DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}
if(token!= IntPtr.Zero)
CloseHandle(token);
if(tokenDuplicate!=IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}
private void undoImpersonation()
{
impersonationContext.Undo();
}
</script>
Visual J# .NET
<%@ Page language="VJ#" %>
<%@ Import Namespace="System.Web" %>
<%@ Import Namespace="System.Web.Security" %>
<%@ Import Namespace="System.Security.Principal" %>
<%@ Import Namespace="System.Runtime.InteropServices" %>
<script runat=server>
öffentliches statisches int LOGON32_LOGON_INTERACTIVE = 2;
öffentliches statisches int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext impersonationContext;
/** @attribute DllImport("advapi32.dll") */
public static native int LogonUserA(String lpszUserName,
Zeichenfolge lpszDomain,
String 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 impersonationLevel,
System.IntPtr[] hNewToken);
/** @attribute DllImport("kernel32.dll",CharSet=CharSet.Auto) */
public static native boolean CloseHandle(System.IntPtr[] handle);
/** @attribute DllImport("advapi32.dll",
CharSet=CharSet.Auto,SetLastError=true) */
public static native boolean RevertToSelf();
public void Page_Load(Object s, System.EventArgs e)
{
if(impersonateValidUser("Benutzername", "Domäne", "Passwort"))
{
//Fügen Sie hier Ihren Code ein, der im Sicherheitskontext eines bestimmten Benutzers ausgeführt wird.
undoImpersonation();
}
anders
{
//Ihr Identitätswechsel ist fehlgeschlagen. Fügen Sie daher hier einen ausfallsicheren Mechanismus ein.
}
}
privater boolescher Wert impersonateValidUser(String Benutzername, String Domäne, String Passwort)
{
WindowsIdentity tempWindowsIdentity;
System.IntPtr[] token = new System.IntPtr[1];
System.IntPtr[] tokenDuplicate = new System.IntPtr[1];
if(RevertToSelf())
{
if(LogonUserA(Benutzername, Domäne, Passwort, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, Token) != 0)
{
if(DuplicateToken(token[0], 2, tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate[0]);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(tokenDuplicate);
CloseHandle(token);
return true;
}
}
}
}
if(!token[0].Equals(System.IntPtr.Zero))
CloseHandle(token);
if(!tokenDuplicate[0].Equals(System.IntPtr.Zero))
CloseHandle(tokenDuplicate);
return false;
}
private void undoImpersonation()
{
impersonationContext.Undo();
}
</script>
Hinweis: Die Identität des Prozesses, der sich als ein bestimmter Benutzer in einem Thread ausgibt, muss über die Berechtigung „Als Teil des Betriebssystems“ verfügen. Standardmäßig wird der Prozess Aspnet_wp.exe unter einem Computerkonto namens ASPNET ausgeführt. Dieses Konto verfügt jedoch nicht über die erforderlichen Berechtigungen, um sich als ein bestimmter Benutzer auszugeben. Wenn Sie versuchen, sich als ein bestimmter Benutzer auszugeben, wird eine Fehlermeldung angezeigt.
Um dieses Problem zu beheben, verwenden Sie eine der folgenden Methoden:
•
Erteilen Sie dem ASPNET-Konto die Berechtigung „Als Teil des Betriebssystems agieren“.
•
Ändern Sie im Konfigurationsabschnitt <processModel> der Datei Machine.config das Konto, unter dem der Prozess Aspnet_wp.exe ausgeführt wird, in das Systemkonto.