Было установлено, что 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 () неожиданно вернул true.
Второй тест - это веб-сайт. Я поместил тот же код в (заменил Console.Write на literal1.Text = string.Format): IsInRole () вернул true, без открытия ключа открытия, IIS7.5: анонимная аутентификация, пул приложений: классический конвейер, ApplicationPoolIdentity, платформа 2.0, 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 не будет выполнять никаких дополнительных проверок безопасности (как говорят в документации) для этой ссылки даже после окончания олицетворения.
Полагаю, мне придется делать олицетворение каждый раз, когда мне нужно записать в реестр. (