在 C# 中,如何设置线程的标识?
例如,如果我有 Thread MyThread,它已经启动,我可以更改 MyThread 的身份吗?
或者这是不可能的?
在 C# 中,如何设置线程的标识?
例如,如果我有 Thread MyThread,它已经启动,我可以更改 MyThread 的身份吗?
或者这是不可能的?
您可以通过创建新的 Principal 来设置线程的标识。您可以使用从System.Security.Principal.IIdentity继承的任何 Identity ,但您需要一个从System.Security.Principal.IPrincipal继承的类,该类采用您正在使用的 Identity 类型。
为简单起见,.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;
}
但是,这不会给您使用新身份的 Windows 权限。但如果您正在开发一个网站并想要创建自己的用户管理,它会很有用。
如果您想伪装成与您当前使用的帐户不同的 Windows 用户,那么您需要使用模拟。可以在System.Security.Principal.WindowsIdentity.Impersonate()的帮助中找到如何执行此操作的示例。您运行的帐户可以模拟哪些帐户存在限制。
在某些情况下,.Net 框架会为您进行模拟。发生这种情况的一个例子是,如果您正在开发一个 ASP.Net 网站,并且您为正在运行的虚拟目录或网站打开了集成 Windows 身份验证。
已接受答案的更新 [仅适用于 .NET framework 4.5 及更高版本]
在.NET 4.5
该属性IsAuthenticated
中没有设置访问器,因此您不能将其直接设置为已接受的答案。
您可以使用以下代码设置该属性。
GenericIdentity identity = new GenericIdentity("someuser", "Forms");
Thread.CurrentPrincipal = new GenericPrincipal(identity, new string[] { "somerole" });
是的,从字面上使用模仿
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);
}
}
}