Nếu sử dụng mã như sau để mạo danh người dùng khác,.NET có phải là trình duyệt đăng nhập an toàn chủ đề không?
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool
LogonUser(string lpszUsername, string lpszDomain,
string lpszPassword, int dwLogonType,
int dwLogonProvider, ref IntPtr phToken);
var handle = IntPtr.Zero;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_PROVIDER_DEFAULT = 0;
const int SecurityImpersonation = 2;
LogonUser(username, domain,
password, LOGON32_LOGON_NETWORK,
LOGON32_PROVIDER_DEFAULT, ref handle))
trên hai luồng đồng thời khác nhau, họ sẽ can thiệp với nhau? Tức là, hiện tại người dùng đã đăng nhập có được liên kết với luồng hay với quy trình lưu trữ không?
Tôi đang sử dụng trình quản lý đăng nhập để tạo đối tượng WindowsImpersonationContext, dưới dạng trường trạng thái riêng tư trong một phiên bản của loại tôi đặt tên là "Trình mạo danh" (mã bên dưới). Vì vậy, vì đối tượng WindowsImpersonationContext này là một trường private cục bộ trong một thể hiện kiểu này, và một cá thể mới của kiểu này được tạo ra mỗi khi tôi muốn mạo danh một số thông tin xác thực, tôi có thể giả định rằng WindowsImpersonationContext này là những gì đang được sử dụng để thực hiện tất cả kiểm chứng thực ACL trong thực thi mã trong một khối như
using (Impersonator.Impersonate(userId, domain, password))
{
// Code I want to execute using supplied credentials
}
gì có tôi quan tâm là tuyên bố trên MSDN trang WindowsImpersonationContext nói rằng:
Bất kỳ public static (chung trong Visual Basic) các thành viên thuộc loại này là chủ đề an toàn. Bất kỳ thành viên cá thể nào cũng không được bảo đảm là luồng an toàn.
Impersonator
lớp:
public class Impersonator: IDisposable
{
#region Declarations
private readonly string username;
private readonly string password;
private readonly string domain;
// This will hold the security context
// for reverting back to the client after
// impersonation operations are complete
private WindowsImpersonationContext impersonationContext;
#endregion Declarations
#region Constructors
public Impersonator(string UserName,
string Domain, string Password)
{
username = UserName;
domain = Domain;
password = Password;
}
#endregion Constructors
#region Public Methods
public static Impersonator Impersonate(
string userName, string domain, string password)
{
var imp = new Impersonator(userName, domain, password);
imp.Impersonate();
return imp;
}
public void Impersonate()
{
impersonationContext = Logon().Impersonate();
}
public void Undo() {
impersonationContext.Undo();
}
#endregion Public Methods
#region Private Methods
private WindowsIdentity Logon()
{
var handle = IntPtr.Zero;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_PROVIDER_DEFAULT = 0;
const int SecurityImpersonation = 2;
// Attempt to authenticate domain user account
try
{
if (!LogonUser(username, domain,
password, LOGON32_LOGON_NETWORK,
LOGON32_PROVIDER_DEFAULT, ref handle))
throw new LogonException(
"User logon failed. Error Number: " +
Marshal.GetLastWin32Error());
// ----------------------------------
var dupHandle = IntPtr.Zero;
if (!DuplicateToken(handle,
SecurityImpersonation,
ref dupHandle))
throw new LogonException(
"Logon failed attemting to duplicate handle");
// Logon Succeeded ! return new WindowsIdentity instance
return (new WindowsIdentity(handle));
}
// Close the open handle to the authenticated account
finally { CloseHandle(handle); }
}
#region external Win32 API functions
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool
LogonUser(string lpszUsername, string lpszDomain,
string lpszPassword, int dwLogonType,
int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);
// --------------------------------------------
[DllImport("advapi32.dll", CharSet = CharSet.Auto,
SetLastError = true)]
public static extern bool DuplicateToken(
IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL,
ref IntPtr DuplicateTokenHandle);
// --------------------------------------------
#endregion external Win32 API functions
#endregion Private Methods
#region IDisposable
private bool disposed;
public void Dispose() { Dispose(true); }
public void Dispose(bool isDisposing)
{
if (disposed)
return;
if (isDisposing)
Undo();
// -----------------
disposed = true;
GC.SuppressFinalize(this);
}
~Impersonator() {
Dispose(false);
}
#endregion IDisposable
}
Phải, tôi sử dụng tay cầm đó để tạo một đối tượng WindowsImpersonationContext, đó là chủ đề an toàn IS, (nó là một thể hiện của một kiểu xác định được tạo ra một lần cho mỗi lần sử dụng). Bởi "liên quan", tôi có nghĩa là nơi xử lý đăng nhập được lưu trữ? Khi tôi hiểu nó, nó là đối tượng WindowsImpersonationContext này "giữ" tham chiếu đến bối cảnh bảo mật, và nếu điều này không được chia sẻ qua các chủ đề tôi nên được ok ... phải không? –
Điều gì khiến tôi lo ngại là tuyên bố trên trang msdn http://msdn.microsoft.com/en-us/library/system.security.principal.windowsimpersonationcontext.aspx có nội dung: "Bất kỳ tĩnh công cộng nào (Được chia sẻ trong Visual Basic) các thành viên thuộc loại này là an toàn chủ đề. Bất kỳ thành viên nào cũng không được bảo đảm là luồng an toàn. " –
@Charles Bretana: Các cá thể thành viên của cá thể WindowsImpersonationContext KHÔNG phải là chủ đề an toàn. Bạn không thể thực hiện cuộc gọi đến cùng một phiên bản từ nhiều luồng với bảo đảm an toàn. Đối tượng này cũng giống như hầu hết các đối tượng khác trong .NET, các thành viên instance không phải là thread-safe, các thành viên tĩnh là. Đối với nơi lưu trữ đăng nhập, bộ điều khiển nằm trong IntPtr, trỏ đến thông tin cho mã thông báo đăng nhập. – casperOne