Как в C# установить идентичность потока?
Например, если у меня уже запущен поток MyThread, могу ли я изменить идентификатор MyThread?
Или это невозможно?





Да, буквально используя выдача себя за другое лицо
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);
}
}
}
На удивление эта ссылка помогла мне решить мою проблему. Хотя он не устанавливает идентификатор потока, он позволяет запускать код, выдавая себя за другого пользователя. Изучив первый пример в ссылке, я сделал копию текущего идентификатора пользователя в основном потоке, используя: var newId = WindowsIdentity.GetCurrent (); Впоследствии я передал это удостоверение своим потокам и олицетворял пользователя с помощью этого предложения: using (var impersonationContext = newId.Impersonate ()) Код, выполняемый внутри using, будет выполняться под олицетворенным удостоверением.
@ Пол действительно, это оказалось полезным и для меня, думаю, я обновлю ответ, так как это немного свет в ретроспективе
Вы можете установить идентификатор потока, создав нового участника. Вы можете использовать любую идентичность, которая наследуется от System.Security.Principal.IIdentity, но вам нужен класс, наследующий от System.Security.Principal.IPrincipal, который принимает тип используемой вами идентичности.
Для простоты .Net framework предоставляет классы 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 для виртуального каталога или сайта, на котором вы работаете.
Если вы используете GenericIdentity Constructor (String, String), вы можете пропустить бит IsAuthenticated = true.
Я использую .NET 4.5, и я не могу скомпилировать этот идентификатор оператора. IsAuthenticated = true; Поскольку свойство IsAuthenticated имеет только метод доступа, не могли бы вы сделать обновление для кода, в котором используется платформа .NET 4.5. в любом случае спасибо, ваш код мне помог (с некоторыми изменениями)
Я изменил ваш код в .NET 4.5 следующим образом, чтобы он работал. GenericIdentity identity = new GenericIdentity ("user1", "Forms"); Thread.CurrentPrincipal = новый GenericPrincipal (идентификатор, новая строка [] {"роль1"}); вы можете использовать этот код, чтобы обновить свой полезный пост, еще раз спасибо.
Будет ли это работать с включенной Windows Authe и Forms Auth на веб-сайте IIS?
Обновление принятого ответа [применимо ТОЛЬКО для .NET framework 4.5 и более поздних версий]
В .NET 4.5 свойство IsAuthenticated не имеет установленного аксессора, поэтому вы не можете установить его напрямую в качестве принятого ответа.
Для установки этого свойства можно использовать следующий код.
GenericIdentity identity = new GenericIdentity("someuser", "Forms");
Thread.CurrentPrincipal = new GenericPrincipal(identity, new string[] { "somerole" });
Будет ли это работать с включенной Windows Authe и Forms Auth на веб-сайте IIS?
Гипотетически, да, это должно быть, потому что в конце концов это новый синтаксис, который вы должны использовать, если вы используете платформу 4.5 .NET и выше.
Вы можете уточнить? Если MyThread уже был запущен, можем ли мы изменить его CurrentPrincipal?