2008-11-03 20 views
20

Trong C#, làm thế nào để tôi thiết lập nhận dạng của một chủ đề?Đặt danh tính của chủ đề

Ví dụ: nếu tôi có Chủ đề MyThread, đã bắt đầu, tôi có thể thay đổi Nhận dạng của MyThread không?

Hoặc điều này là không thể?

Trả lời

27

Bạn có thể đặt Danh tính của chuỗi bằng cách tạo một Hiệu trưởng mới. Bạn có thể sử dụng bất kỳ Danh tính nào được kế thừa từ System.Security.Principal.IIdentity, nhưng bạn cần một lớp kế thừa từ System.Security.Principal.IPrincipal có loại Nhận dạng bạn đang sử dụng.
Để đơn giản vì khuôn khổ Net cung cấp GenericPrincipalGenericIdentity lớp mà có thể được sử dụng như thế này:

using System.Security.Principal; 

// ... 
GenericIdentity identity = new GenericIdentity("M.Brown"); 
identity.IsAuthenticated = true; 

// ... 
System.Threading.Thread.CurrentPrincipal = 
    new GenericPrincipal(
     identity, 
     new string[] { "Role1", "Roll2" } 
    ); 

//... 
if (!System.Threading.Thread.CurrentPrincipal.IsInRole("Roll1")) 
{ 
     Console.WriteLine("Permission denied"); 
     return; 
} 

này sẽ không cung cấp cho bạn tuy nhiên cửa sổ quyền sử dụng thứ bản sắc mới. Nhưng nó có thể hữu ích nếu bạn đang phát triển một trang web và muốn tạo quản lý người dùng của riêng bạn.

Nếu bạn muốn giả vờ là người dùng Windows khác với tài khoản bạn hiện đang sử dụng thì bạn cần sử dụng mạo danh. Bạn có thể tìm thấy ví dụ về cách thực hiện việc này trong Trợ giúp cho System.Security.Principal.WindowsIdentity.Impersonate(). Có những giới hạn về tài khoản mà bạn đang chạy có thể mạo danh.

Trong một số trường hợp, khung công tác Net đóng vai trò mạo danh cho bạn. Một ví dụ về nơi điều này xảy ra là nếu bạn đang phát triển một trang web ASP.Net và bạn đã tích hợp Windows Authentication được bật cho thư mục ảo hoặc trang web bạn đang chạy.

+0

Nếu bạn sử dụng ['GenericIdentity Constructor (String, String)'] (http: // msdn. microsoft.com/en-us/library/2wh03ckb(v=vs.110).aspx) bạn có thể bỏ qua bit 'IsAuthenticated = true'. –

+0

Tôi đang sử dụng .NET 4.5 và tôi không thể biên dịch câu lệnh này identity.IsAuthenticated = true; vì thuộc tính "IsAuthenticated" chỉ nhận được accessor, bạn có thể vui lòng, cập nhật mã trong trường hợp sử dụng .NET 4.5 framework.cảm ơn bạn bất kỳ cách nào, mã của bạn đã giúp tôi, (với một số sửa đổi) –

+1

Tôi đã sửa đổi mã của bạn trong .NET 4.5 như sau để làm cho nó hoạt động Generic Identity identity = new GenericIdentity ("user1", "Forms"); Thread.CurrentPrincipal = new GenericPrincipal (danh tính, chuỗi mới [] {"role1"}); bạn có thể sử dụng mã này để cập nhật cho bạn bài đăng hữu ích, cảm ơn bạn một lần nữa. –

3

Vâng, sử dụng impersonation nghĩa đen

using (new Impersonation()) 
{ 
    // your elevated code 
} 

và lớp là như sau, đối với các thiết lập tôi sử dụng lâu đài bộ chuyển đổi từ điển nếu nó trông lạ.

[PermissionSet(SecurityAction.Demand, Name = "FullTrust")] 
public class Impersonation : IDisposable 
{ 
    private readonly SafeTokenHandle _handle; 
    private readonly WindowsImpersonationContext _context; 

    //const int Logon32LogonNewCredentials = 9; 
    private const int Logon32LogonInteractive = 2; 

    public Impersonation() 
    { 
     var settings = Settings.Instance.Whatever; 
     var domain = settings.Domain; 
     var username = settings.User; 
     var password = settings.Password; 
     var ok = LogonUser(username, domain, password, Logon32LogonInteractive, 0, out _handle); 
     if (!ok) 
     { 
      var errorCode = Marshal.GetLastWin32Error(); 
      throw new ApplicationException(string.Format("Could not impersonate the elevated user. LogonUser returned error code {0}.", errorCode)); 
     } 
     _context = WindowsIdentity.Impersonate(_handle.DangerousGetHandle()); 
    } 

    public void Dispose() 
    { 
     _context.Dispose(); 
     _handle.Dispose(); 
    } 

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
    private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken); 

    public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid 
    { 
     private SafeTokenHandle() 
      : base(true) 
     { } 

     [DllImport("kernel32.dll")] 
     [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
     [SuppressUnmanagedCodeSecurity] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     private static extern bool CloseHandle(IntPtr handle); 

     protected override bool ReleaseHandle() 
     { 
      return CloseHandle(handle); 
     } 
    } 
} 
+0

Bạn có thể xây dựng không? Nếu MyThread đã chạy, chúng ta có thể thay đổi CurrentPrincipal của nó không? – Duncan

+0

có, bạn đã theo liên kết chưa? có những ví dụ ở đó. – dove

+0

Đáng ngạc nhiên là liên kết này đã giúp tôi giải quyết vấn đề của mình. Mặc dù nó không đặt danh tính Chủ đề, nó cho phép bạn chạy mã trong khi mạo danh người dùng khác. Bằng cách kiểm tra ví dụ đầu tiên trong liên kết, tôi đã tạo một bản sao danh tính người dùng hiện tại trong chủ đề chính của mình bằng cách sử dụng: var newId = WindowsIdentity.GetCurrent(); Sau đó, tôi đã chuyển danh tính này đến các luồng của mình và mạo danh người dùng với mệnh đề này: using (var impersonationContext = newId.Impersonate()) Mã được thực thi bên trong việc sử dụng sẽ chạy dưới danh tính Mạo danh. – Sal

3

Đây là bản cập nhật cho câu trả lời được chấp nhận [ áp dụng trên Khuôn khổ .NET 4.5 trở lên]
Trong .NET 4.5 thuộc tính IsAuthenticated không có bộ truy cập được đặt, do đó bạn không thể đặt trực tiếp làm câu trả lời được chấp nhận.
Bạn có thể sử dụng mã sau để thiết lập thuộc tính đó.

GenericIdentity identity = new GenericIdentity("someuser", "Forms"); 
Thread.CurrentPrincipal = new GenericPrincipal(identity, new string[] { "somerole" }); 
Các vấn đề liên quan