"Mạo danh" trong không gian .NET thường có nghĩa là chạy mã trong một tài khoản người dùng cụ thể. Đây là một khái niệm hơi riêng biệt so với việc truy cập vào tài khoản người dùng đó thông qua tên người dùng và mật khẩu, mặc dù hai ý tưởng này kết hợp với nhau thường xuyên. Tôi sẽ mô tả cả hai, và sau đó giải thích cách sử dụng thư viện SimpleImpersonation của tôi , sử dụng chúng trong nội bộ.
mạo danh
Các API để mạo danh được cung cấp trong .NET thông qua System.Security.Principal
không gian tên:
Mã mới hơn (.NET 4.6+, .NET Core, v.v.) thường nên sử dụng WindowsIdentity.RunImpersonated
, chấp nhận xử lý mã thông báo của tài khoản người dùng và sau đó Action
hoặc Func<T>
để mã thực thi.
WindowsIdentity.RunImpersonated(tokenHandle, () =>
{
// do whatever you want as this user.
});
hoặc là
var result = WindowsIdentity.RunImpersonated(tokenHandle, () =>
{
// do whatever you want as this user.
return result;
});
Mã cũ hơn đã sử dụng WindowsIdentity.Impersonate
phương thức để lấy một WindowsImpersonationContext
đối tượng. Đối tượng này thực hiện IDisposable
, do đó thường được gọi từ một using
khối.
using (WindowsImpersonationContext context = WindowsIdentity.Impersonate(tokenHandle))
{
// do whatever you want as this user.
}
Mặc dù API này vẫn tồn tại trong .NET Framework, nhưng nói chung nên tránh và không có sẵn trong .NET Core hoặc .NET Standard.
Truy cập tài khoản người dùng
API để sử dụng tên người dùng và mật khẩu để có quyền truy cập vào tài khoản người dùng trong Windows là LogonUser
- đó là API gốc Win32. Hiện tại không có API .NET tích hợp để gọi nó, vì vậy người ta phải dùng đến P / Invoke.
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
Đây là định nghĩa cuộc gọi cơ bản, tuy nhiên còn nhiều điều cần xem xét để thực sự sử dụng nó trong sản xuất:
- Có được một tay cầm với mẫu truy cập "an toàn".
- Đóng tay cầm bản địa một cách thích hợp
- Mức tin cậy bảo mật truy cập mã (CAS) (chỉ trong .NET Framework)
- Vượt qua
SecureString
khi bạn có thể thu thập một cách an toàn thông qua tổ hợp phím người dùng.
Số lượng mã để viết để minh họa tất cả những điều này vượt quá mức cần có trong câu trả lời của StackOverflow, IMHO.
Cách tiếp cận kết hợp và dễ dàng hơn
Thay vì tự viết tất cả những điều này, hãy xem xét sử dụng thư viện SimpleImpersonation của tôi , kết hợp việc mạo danh và truy cập người dùng vào một API duy nhất. Nó hoạt động tốt trong cả cơ sở mã hiện đại và cũ hơn, với cùng một API đơn giản:
var credentials = new UserCredentials(domain, username, password);
Impersonation.RunAsUser(credentials, logonType, () =>
{
// do whatever you want as this user.
});
hoặc là
var credentials = new UserCredentials(domain, username, password);
var result = Impersonation.RunAsUser(credentials, logonType, () =>
{
// do whatever you want as this user.
return something;
});
Lưu ý rằng nó rất giống với WindowsIdentity.RunImpersonated
API, nhưng không yêu cầu bạn biết bất cứ điều gì về việc xử lý mã thông báo.
Đây là API kể từ phiên bản 3.0.0. Xem readme dự án để biết thêm chi tiết. Cũng lưu ý rằng phiên bản trước của thư viện đã sử dụng API có IDisposable
mẫu, tương tự như WindowsIdentity.Impersonate
. Phiên bản mới hơn an toàn hơn nhiều, và cả hai vẫn được sử dụng nội bộ.