web-dev-qa-db-ja.com

スレッドのIDを設定する

C#で、スレッドのIDを設定するにはどうすればよいですか?

たとえば、すでに開始されているThread MyThreadがある場合、MyThreadのIDを変更できますか?

それともこれは不可能ですか?

24
Duncan

新しいプリンシパルを作成することにより、スレッドのIDを設定できます。 System.Security.Principal.IIdentity から継承する任意のIDを使用できますが、 System.Security.Principal.IPrincipal から継承するクラスが必要です。使用しているID。
簡単にするために、.Netフレームワークは次のように使用できる GenericPrincipal および GenericIdentity クラスを提供します。

 using System.Security.Principal;

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

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

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

ただし、これでは、新しいIDを使用するものに対するWindowsの権限は付与されません。ただし、Webサイトを開発していて、独自のユーザー管理を作成したい場合に役立ちます。

現在使用しているアカウントとは異なるWindowsユーザーのふりをしたい場合は、偽装を使用する必要があります。これを行う方法の例は、 System.Security.Principal.WindowsIdentity.Impersonate() のヘルプにあります。実行しているアカウントが偽装できるアカウントには制限があります。

場合によっては、.Netフレームワークが偽装を行います。これが発生する1つの例は、ASP.Net Webサイトを開発していて、実行している仮想ディレクトリまたはサイトに対して統合Windows認証がオンになっている場合です。

29
Martin Brown

受け入れられた回答の更新[.NET Framework 4.5以降にのみ適用]
In .NET 4.5プロパティIsAuthenticatedにはアクセサが設定されていないため、受け入れられた回答のように直接設定することはできません。
次のコードを使用して、そのプロパティを設定できます。

GenericIdentity identity = new GenericIdentity("someuser", "Forms");
Thread.CurrentPrincipal = new GenericPrincipal(identity, new string[] { "somerole" });
4
Hakan Fıstık

はい、 なりすまし を文字通り使用します

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

クラスは次のとおりです。設定については、奇妙に見える場合は城辞書アダプターを使用します。

[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);
        }
    }
}
3
dove