Configured impersonation, described in the article How to use Configured Impersonation in ASP.NET, allows you to impersonate a user for the entire duration of a request. By using programmatic impersonation (based on the WindowsIdentity.Impersonate() method) , you have more control, such as the ability to impersonate a user for only part of the page request. This method sets up impersonation for a specific account. You identify the account you want to impersonate by using its account token. Account tokens are what Windows uses to track users once their credentials are approved. If you have the token for a user, you can impersonate that user.
The general process is as follows:
1. Obtain an account token for the account you want to impersonate.
2. Use WindowsIdentity.Impersonate() to start impersonation. This method returns a WindowsImpersonationContext object.
3. Call the Undo() method of the WindowsImpersonationContext object to revert to the original identity.
You can get an account token in two main ways:
1. The most common approach is to retrieve the token for the currently authenticated user, by using the WindowsIdentity.Token property. Tokens are represented in .NET as IntPtr objects, which are representations of pointers to unmanaged memory locations, but you never need to interact with this directly. You need to pass the token to the WindowsIdentity.Impersonate() method:
If TypeOf (User) Is WindowsPrincipal Then
Dim Principal As WindowsPrincipal = DirectCast(User, WindowsPrincipal)
Dim Identity As WindowsIdentity = DirectCast(Principal.Identity, WindowsIdentity)
Dim Token As IntPtr = Identity.Token
End If
2. You can get a user token by logging in with a specific user name and password. Unfortunately, .NET does not provide managed classes for logging a user in and you must use the LogonUser() function from the unmanaged Win32 security API.
2.1. You must first declare it as shown:
<DllImport(“c:\Windows\System32\advapi32.dll”)> _
Public Shared Function LogonUser(lpszUserName As String, lpszDomain As String, lpszPassword As String, dwLogonType As Integer, dwLogonProvider As Integer, ByRef phToken As Integer) As Boolean
End Function
This code uses the DllImport attribute, which tells the runtime that you are going to access a native Windows API located in the native DLL advapi32.dll in the Windows system directory. The types of the parameters in the function prototype where this attribute is applied to need to map to the types of the functions encapsulated into the native DLL. Although every call to this method in your code looks like a call to any other static method of a .NET class, in reality the call gets routed to the native method encapsulated in the DLL specified in the DllImport attribute, and the information transmitted gets marshaled accordingly.
2.2. You can use the LoginUser() function it in your code to log the user in, as shown:
Imports System
Imports System.Runtime.InteropServices
Imports System.Collections.Generic
Imports System.Linq
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Partial Class ImpersonationVB
Inherits System.Web.UI.Page
‘ You should include System.Runtime.InteropServices
<DllImport(“c:\Windows\System32\advapi32.dll”)> _
Public Shared Function LogonUser(lpszUserName As String, lpszDomain As String, lpszPassword As String, dwLogonType As Integer, dwLogonProvider As Integer, ByRef phToken As Integer) As Boolean
End Function
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles LblLegend.Load
Test1()
End Sub
Protected Sub Test1()
Dim User As String = “user”
Dim Password As String = “password”
Dim Machine As String = “thepc”
Dim ReturnedToken As Integer
If LogonUser(User, Machine, Password, 3, 0, ReturnedToken) Then
Dim Token As IntPtr = New IntPtr(ReturnedToken)
LblLegend.Text = “Token = ” + Token.ToString()
End If
End Sub
End Class
2.3. You must convert the integer value returned by LogonUser() into an IntPtr in order to use it with the WindowsIdentity.Impersonate() method.