Ответ 1
Было показано, что LogonUser() возвращает только ограниченный токен. При поиске подтверждения я получил сообщение о том, что LogonUser() вернул ограниченный токен только для сеансов. Я создал пару тестов, чтобы узнать.
Первое - это консольное приложение:
using (ECR.Impersonator imp = new ECR.Impersonator("XXX", "XXX", "XXX"))
{
WindowsIdentity ident = WindowsIdentity.GetCurrent();
WindowsPrincipal princ = new WindowsPrincipal(ident);
Console.WriteLine("{0}, {1}", ident.Name, princ.IsInRole(WindowsBuiltInRole.Administrator));
RegistryKey root = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Connection Strings", RegistryKeyPermissionCheck.ReadWriteSubTree);
RegistryKey key = root.CreateSubKey("AbacBill", RegistryKeyPermissionCheck.ReadWriteSubTree);
}
При запуске в повышенной консоли IsInRole() вернётся true и нет ошибки при открытии этого раздела. При запуске в не-поднятой консоли IsInRole() возвратил true и с ошибкой открыл подраздел:
Unhandled Exception: System.IO.IOException: Unknown error "1346".
at Microsoft.Win32.RegistryKey.Win32Error(Int32 errorCode, String str)
at Microsoft.Win32.RegistryKey.CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck, RegistrySecurity registrySecurity)
at test.Program.test14()
at test.Program.Main(String[] args)
Итак, похоже, что в невысокой интерактивной сессии LogonUser() действительно возвращает ограниченный токен. Интересно, что нормальный тест на выполнение IsInRole() неожиданно вернулся.
Второй тест - это веб-сайт. Я поместил тот же код в (заменил Console.Write на literal1.Text = string.Format): IsInRole() вернётся true, нет раздела для открытия ошибки, IIS7.5: анонимная аутентификация, пул приложений: классический конвейер, ApplicationPoolIdentity, 2.0 framework, web.config: режим аутентификации = нет, без олицетворения.
Таким образом, это подтверждает мое впечатление, что LogonUser() возвращает ограниченный токен только для интерактивных сеансов, но неинтерактивные сеансы получают полный токен.
Выполнение этих тестов помогло мне ответить на мой собственный вопрос. Моя библиотека классов в основном используется в веб-приложениях, и они постоянно боятся при применении обновлений конфигурации (доступ запрещен при открытии подраздела). Поэтому я изменил свой тест, чтобы более точно отразить то, что я делаю (выдавая себя за ссылку на мой корневой ключ):
protected void Page_Load(object sender, EventArgs e)
{
RegistryKey root = null;
using (ECR.Impersonator imp = new ECR.Impersonator("XXX", "XXX", "XXX"))
{
WindowsIdentity ident = WindowsIdentity.GetCurrent();
WindowsPrincipal princ = new WindowsPrincipal(ident);
lit.Text = string.Format("{0}, {1}", ident.Name, princ.IsInRole(WindowsBuiltInRole.Administrator));
root = Registry.LocalMachine.CreateSubKey("SOFTWARE\\XXX", RegistryKeyPermissionCheck.ReadWriteSubTree);
}
root.SetValue("test", "test");
RegistryKey key = root.CreateSubKey("XXX", RegistryKeyPermissionCheck.ReadWriteSubTree);
}
и ошибки:
[UnauthorizedAccessException: Access to the registry key 'HKEY_LOCAL_MACHINE\SOFTWARE\XXX\XXX' is denied.]
Microsoft.Win32.RegistryKey.Win32Error(Int32 errorCode, String str) +3803431
Microsoft.Win32.RegistryKey.CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck, RegistrySecurity registrySecurity) +743
webtest.impTest.Page_Load(Object sender, EventArgs e) in D:\VS 2008 Projects\test\webtest\impTest.aspx.cs:28
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +25
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +42
System.Web.UI.Control.OnLoad(EventArgs e) +132
System.Web.UI.Control.LoadRecursive() +66
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2428
Опять же, никаких проблем с записью значений в мой корневой ключ, просто открытие дочерних элементов. Таким образом, похоже, что использование RegistryKeyPermissionCheck.ReadWriteSubTree действительно не выполняет никаких дополнительных проверок безопасности при написании этого ключа, но делает другую проверку безопасности при открытии подраздела даже с RegistryKeyPermissionCheck.ReadWriteSubTree(хотя документы говорят, что это не так).
Ответ на мой вопрос заключается в том, что он соответствующим образом предоставляет повышенные разрешения посредством олицетворения под неинтерактивным входом. Моя проблема в том, что я предположил, что RegistryKeyPermissionCheck.ReadWriteSubTree не будет делать никаких дальнейших проверок безопасности (например, документы) на этой ссылке даже после того, как завершается олицетворение.
Думаю, мне придется делать олицетворение каждый раз, когда мне нужно писать в реестр.: (