| 

.NET C# Java Javascript Exception

5
Ich habe gerade eine interessante Anforderung hereinbekommen. Mein Kunde möchte mit einem Programm auf einem File-Share schreibend zugreifen, auf den der Benutzer, der das Programm ausführt nur Leserechte hat. Im ASP.NET-Umfeld gibt es ja das Konzept der Impersonation, mit dem ich in einem bestimmten Benutzerkontext arbeiten kann. Gibt es so etwas auch für Windows-Forms Anwendungen?

Danke im Voraus für eure Tips
Klaus
News:
28.03.2013
luedi 2,0k 1 9
1 Antwort
3
Das ist nicht von dem Umfeld abhängig, Du kannst Impersonation auch in WinForms einsetzen.
Versuche es mal mit der folgenden Klasse:
namespace Tools
{
#region Using directives.
// ----------------------------------------------------------------------

using System;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.ComponentModel;

// ----------------------------------------------------------------------
#endregion

/////////////////////////////////////////////////////////////////////////

/// <summary>
/// Impersonation of a user. Allows to execute code under another
/// user context.
/// Please note that the account that instantiates the Impersonator class
/// needs to have the 'Act as part of operating system' privilege set.
/// </summary>
/// <remarks>
/// This class is based on the information in the Microsoft knowledge base
/// article http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306158
///
/// Encapsulate an instance into a using-directive like e.g.:
///
/// ...
/// using ( new Impersonator( "myUsername", "myDomainname", "myPassword" ) )
/// {
/// ...
/// [code that executes under the new context]
/// ...
/// }
/// ...
///
/// </remarks>
public class Impersonator :
IDisposable
{
[StructLayout(LayoutKind.Sequential)]
public struct ProfileInfo
{
///
/// Specifies the size of the structure, in bytes.
///
public int dwSize;

///
/// This member can be one of the following flags:
/// PI_NOUI or PI_APPLYPOLICY
///
public int dwFlags;

///
/// Pointer to the name of the user.
/// This member is used as the base name of the directory
/// in which to store a new profile.
///
public string lpUserName;

///
/// Pointer to the roaming user profile path.
/// If the user does not have a roaming profile, this member can be NULL.
///
public string lpProfilePath;

///
/// Pointer to the default user profile path. This member can be NULL.
///
public string lpDefaultPath;

///
/// Pointer to the name of the validating domain controller, in NetBIOS format.
/// If this member is NULL, the Windows NT 4.0-style policy will not be applied.
///
public string lpServerName;

///
/// Pointer to the path of the Windows NT 4.0-style policy file.
/// This member can be NULL.
///
public string lpPolicyPath;

///
/// Handle to the HKEY_CURRENT_USER registry key.
///
public IntPtr hProfile;
}

IntPtr tokenDuplicate = IntPtr.Zero;
ProfileInfo profileInfo;

#region Public methods.


[DllImport("userenv.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool LoadUserProfile
(IntPtr hToken, ref ProfileInfo lpProfileInfo);

[DllImport("Userenv.dll", CallingConvention =
CallingConvention.Winapi, SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool UnloadUserProfile
(IntPtr hToken, IntPtr lpProfileInfo);
// ------------------------------------------------------------------

/// <summary>
/// Constructor. Starts the impersonation with the given credentials.
/// Please note that the account that instantiates the Impersonator class
/// needs to have the 'Act as part of operating system' privilege set.
/// </summary>
/// <param name="userName">The name of the user to act as.</param>
/// <param name="domainName">The domain name of the user to act as.</param>
/// <param name="password">The password of the user to act as.</param>
public Impersonator(
string userName,
string domainName,
string password )
{
ImpersonateValidUser( userName, domainName, password );
}

// ------------------------------------------------------------------
#endregion

#region IDisposable member.
// ------------------------------------------------------------------

public void Dispose()
{
UndoImpersonation();
}

// ------------------------------------------------------------------
#endregion

#region P/Invoke.
// ------------------------------------------------------------------

[DllImport("advapi32.dll", SetLastError=true)]
private static extern int LogonUser(
string lpszUserName,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern int DuplicateToken(
IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern bool RevertToSelf();

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern bool CloseHandle(
IntPtr handle);

private const int LOGON32_LOGON_INTERACTIVE = 2;
private const int LOGON32_PROVIDER_DEFAULT = 0;

// ------------------------------------------------------------------
#endregion

#region Private member.
// ------------------------------------------------------------------

/// <summary>
/// Does the actual impersonation.
/// </summary>
/// <param name="userName">The name of the user to act as.</param>
/// <param name="domainName">The domain name of the user to act as.</param>
/// <param name="password">The password of the user to act as.</param>
private void ImpersonateValidUser(
string userName,
string domain,
string password )
{
WindowsIdentity tempWindowsIdentity = null;
IntPtr token = IntPtr.Zero;

if (string.IsNullOrEmpty(domain))
domain = System.Environment.MachineName;
try
{
if ( RevertToSelf() )
{
if ( LogonUser(
userName,
domain,
password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
ref token ) != 0 )
{
if ( DuplicateToken( token, 2, ref tokenDuplicate ) != 0 )
{
tempWindowsIdentity = new WindowsIdentity( tokenDuplicate );
impersonationContext = tempWindowsIdentity.Impersonate();
#region LoadUserProfile
// Load user profile
profileInfo = new ProfileInfo();
profileInfo.dwSize = Marshal.SizeOf(profileInfo);
profileInfo.lpUserName = userName;
profileInfo.dwFlags = 1;
Boolean loadSuccess = LoadUserProfile(tokenDuplicate, ref profileInfo);
if (!loadSuccess)
{
Console.WriteLine("LoadUserProfile() failed with error code: " +
Marshal.GetLastWin32Error());
throw new Win32Exception(Marshal.GetLastWin32Error());
}

if (profileInfo.hProfile == IntPtr.Zero)
{
Console.WriteLine("LoadUserProfile() failed - HKCU handle was not loaded. Error code: " +
Marshal.GetLastWin32Error());
throw new Win32Exception(Marshal.GetLastWin32Error());
}
#endregion



}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
finally
{
if ( token!= IntPtr.Zero )
{
CloseHandle( token );
}
if ( tokenDuplicate!=IntPtr.Zero )
{
CloseHandle( tokenDuplicate );
}
}
}

/// <summary>
/// Reverts the impersonation.
/// </summary>
private void UndoImpersonation()
{
if ( impersonationContext!=null )
{
UnloadUserProfile(tokenDuplicate, profileInfo.hProfile);
impersonationContext.Undo();
}
}

private WindowsImpersonationContext impersonationContext = null;

// ------------------------------------------------------------------
#endregion
}

/////////////////////////////////////////////////////////////////////////
}


Du nutzt es dann in Deiner WinForms-Anwendung wie folgt:
using (Impersonator imp = new Impersonator("test", "ad", "secret"))
{
// Dein Code im anderen usercontext

}
28.03.2013
JEwen 2,7k 5
Danke für die Antwort. Ich werde das nach Ostern gleich ausprobieren.
luedi 28.03.2013

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH