Bạn muốn một phần mã lệnh của bạn thực thi dưới tài khoản của một người dùng khác chứ không phải của người dùng hiện hành.
Đăng nhập vào tài khoản mới bằng hàm không-được-quản-lý LogonUser, và sử dụng phương thức WindowsIdentity.Impersonate.
Theo mặc định, mã lệnh của bạn thực thi dưới identity của người dùng hiện hành. Điều này có nghĩa: mã lệnh của bạn sẽ có khả năng thực hiện bất kỳ hành động nào mà người dùng đó có thể và sẽ bị cản nếu thực hiện bất kỳ hành động nào mà người dùng đó bị cấm. Tuy nhiên, trong một vài trường hợp, bạn muốn mã lệnh của bạn có thể thực thi với các quyền khác với tài khoản người dùng hiện hành. Ví dụ, bạn muốn tạo một ứng dụng chạy thường trực trong một buồng dùng chung ở một cơ quan. Trước khi một người dùng có thể thực hiện các thao tác nào đó (như đọc file), bạn sẽ muốn ứng dụng tạm thời đóng vai identity của người dùng đó để các quyền và hạn chế phù hợp được áp dụng. Hoặc bạn muốn tạo một ứng dụng có thể chạy dưới chế độ “administrator” và “user”. Trong các trường hợp này, bạn sẽ muốn ứng dụng của bạn tạm thời đóng vai một identity khác—quá trình này được gọi là sự giả nhận (impersonation).
Để sử dụng sự giả nhận trong một ứng dụng .NET, bạn cần thực hiện năm bước:
1. Đăng nhập vào tài khoản mới bằng hàm không-được-quản-lý LogonUser (thuộc Windows API¾file advapi32.dll). Hàm này trả về một tham chiếu bộ nhớ đến security token của người dùng.
2. Sao lại token này bằng hàm không-được-quản-lý DuplicateToken (cũng được định nghĩa trong file advapi32.dll).
3. Sử dụng token này để tạo một đối tượng WindowsIdentity mới bằng cách truyền nó cho hàm khởi dựng.
4. Gọi phương thức WindowsIdentity.Impersonate để giả nhận identity mới. Phương thức này trả về một đối tượng WindowsImpersonationContext.
5. Kể từ đây, bạn có thể thực thi mã lệnh dưới tài khoản mới này. Để ngừng giả nhận, gọi phương thức Undo của đối tượng WindowsImpersonationContext.
Ứng dụng Console dưới đây sẽ minh họa các bước này. Để sử dụng đoạn mã này, bạn phải nhập không gian tên System.Security.Principal.
Kết xuất của ứng dụng này có thể như sau:
Đăng nhập vào tài khoản mới bằng hàm không-được-quản-lý LogonUser, và sử dụng phương thức WindowsIdentity.Impersonate.
Theo mặc định, mã lệnh của bạn thực thi dưới identity của người dùng hiện hành. Điều này có nghĩa: mã lệnh của bạn sẽ có khả năng thực hiện bất kỳ hành động nào mà người dùng đó có thể và sẽ bị cản nếu thực hiện bất kỳ hành động nào mà người dùng đó bị cấm. Tuy nhiên, trong một vài trường hợp, bạn muốn mã lệnh của bạn có thể thực thi với các quyền khác với tài khoản người dùng hiện hành. Ví dụ, bạn muốn tạo một ứng dụng chạy thường trực trong một buồng dùng chung ở một cơ quan. Trước khi một người dùng có thể thực hiện các thao tác nào đó (như đọc file), bạn sẽ muốn ứng dụng tạm thời đóng vai identity của người dùng đó để các quyền và hạn chế phù hợp được áp dụng. Hoặc bạn muốn tạo một ứng dụng có thể chạy dưới chế độ “administrator” và “user”. Trong các trường hợp này, bạn sẽ muốn ứng dụng của bạn tạm thời đóng vai một identity khác—quá trình này được gọi là sự giả nhận (impersonation).
Để sử dụng sự giả nhận trong một ứng dụng .NET, bạn cần thực hiện năm bước:
1. Đăng nhập vào tài khoản mới bằng hàm không-được-quản-lý LogonUser (thuộc Windows API¾file advapi32.dll). Hàm này trả về một tham chiếu bộ nhớ đến security token của người dùng.
2. Sao lại token này bằng hàm không-được-quản-lý DuplicateToken (cũng được định nghĩa trong file advapi32.dll).
3. Sử dụng token này để tạo một đối tượng WindowsIdentity mới bằng cách truyền nó cho hàm khởi dựng.
4. Gọi phương thức WindowsIdentity.Impersonate để giả nhận identity mới. Phương thức này trả về một đối tượng WindowsImpersonationContext.
5. Kể từ đây, bạn có thể thực thi mã lệnh dưới tài khoản mới này. Để ngừng giả nhận, gọi phương thức Undo của đối tượng WindowsImpersonationContext.
Ứng dụng Console dưới đây sẽ minh họa các bước này. Để sử dụng đoạn mã này, bạn phải nhập không gian tên System.Security.Principal.
Public Module WindowsSecurityTest ' Hàm API này lấy security token của một người dùng. Private Declare Auto Function LogonUser 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 Private Enum Logon Interactive = 2 NetworkCleartext = 8 End Enum Private Enum Provider [Default] = 0 WindowsNT35 = 1 WindowsNT40 = 2 Windows2000 = 3 End Enum ' Hàm API này sao lại một security token để bạn có thể sử dụng nó. Private Declare Auto Function DuplicateToken Lib "advapi32.dll" _ (ByVal ExistingTokenHandle As IntPtr, _ ByVal ImpersonationLevel As Integer, _ ByRef DuplicateTokenHandle As IntPtr) As Integer Public Sub Main() Console.WriteLine("*** Current User ***") DisplayIdentityInfo() ' Lấy thông tin đăng nhập từ người dùng. Console.WriteLine("Enter the information for the user " & _ "you want to impersonate.") Dim UserName, Domain, Password As String Console.Write("Domain: ") Domain = Console.ReadLine() Console.Write("User Name: ") UserName = Console.ReadLine() Console.Write("Password: ") Password = Console.ReadLine() ' Đăng nhập với identity mới. Dim NewIdentity As WindowsIdentity NewIdentity = GetWindowsIdentity(UserName, Domain, Password) Console.WriteLine() If NewIdentity Is Nothing Then Console.WriteLine("Invalid credentials.") Else ' Giả nhận identity mới. Dim NewContext As WindowsImpersonationContext NewContext = NewIdentity.Impersonate() Console.WriteLine("*** Starting Impersonation ***") DisplayIdentityInfo() ' Trở về identity ban đầu. NewContext.Undo() Console.WriteLine("*** Ending Impersonation ***") DisplayIdentityInfo() End If Console.ReadLine() End Sub ' Hàm này hiển thị thông tin về người dùng hiện hành. Private Sub DisplayIdentityInfo() Dim Identity As WindowsIdentity = WindowsIdentity.GetCurrent() Console.WriteLine("This application is executing as " & _ Identity.Name) Console.WriteLine() End Sub ' Hàm này sử dụng các hàm Win32 API để trả về một đối tượng ' WindowsIdentity đối với một người dùng cho trước. Private Function GetWindowsIdentity(ByVal UserName As String, _ ByVal Domain As String, ByVal Password As String) _ As WindowsIdentity Dim SecurityToken, TokenDuplicate As IntPtr If LogonUser(UserName, Domain, Password, _ Logon.Interactive, Provider.Default, SecurityToken) > 0 Then DuplicateToken(SecurityToken, 2, TokenDuplicate) Return New WindowsIdentity(TokenDuplicate) Else ' Thông tin người dùng không hợp lệ. Return Nothing End If End FunctionEnd Module
Kết xuất của ứng dụng này có thể như sau:
*** Current User ***This application is executing as GOLDSOFT\nnbphuong81Enter the information for the user you want to impersonate.Domain: goldsoftUser Name: testPassword: test*** Starting Impersonation ***This application is executing as GOLDSOFT\test*** Ending Impersonation ***This application is executing as GOLDSOFT\nnbphuong81Windows XP áp đặt một số hạn chế lên việc sử dụng mật khẩu trống để ngăn chặn những cuộc tấn công dựa-vào-mạng (network-based attack). Và kết quả là: bạn không thể sử dụng hàm LogonUser để giả nhận một tài khoản với mật khẩu trống.Trích từ "Các giải pháp lập trình VISUAL BASIC.NET (tập 2)"