Как получить действительный токен пользователя для CreateProcessAsUser?

У меня есть приложение, работающее как обычный пользователь, и служба, работающая как локальная система. Я хочу, чтобы приложение могло сообщить службе, чтобы она снова запускала приложение, как только служба выполнит некоторые другие действия. (Поэтому приложение не будет работать, пока служба выполняет свое «дело».) Чтобы служба могла запускать приложение от имени пользователя, запустившего его первым, ей необходим токен пользователя. Приложение отправляет токен службе перед выходом, но токен/дескриптор недействителен, когда служба пытается его использовать. (Первое, что он делает с ним, это DuplicateTokenEx для получения первичного токена.)

Всегда ли пользовательский токен действителен только в процессе, вызвавшем OpenProcessToken?

Есть ли другой способ сделать это? Я не хочу, чтобы пользователю приходилось «входить» в приложение с помощью logonuser. Это было бы просто глупо. Я думаю, я мог бы передать дескриптор процесса для «explorer.exe» из приложения в службу, которую служба могла бы использовать для получения токена пользователя, но для этого потребовалось бы право доступа PROCESS DUP HANDLE. Я не в восторге от этого решения, но, может быть, это способ сделать это?


person Björn    schedule 07.04.2009    source источник


Ответы (1)


У вас здесь несколько проблем, поэтому я попытаюсь решить их по отдельности, и вы можете исправить меня, если я неправильно понял:

  1. Похоже, у вас есть служба и пользовательское приложение, которые не могут выполнять определенные функции одновременно. Для этого служба останавливает приложение, выполняет специальные функции, а затем перезапускает приложение. Если это так, то, на мой взгляд, у вас есть недостаток дизайна. Вместо того, чтобы останавливать, а затем перезапускать приложение, вы должны координировать доступ к общему ресурсу посредством взаимного исключения, используя именованный мьютекс и/или используя метод IPC, такой как именованные каналы, для передачи намерений.

  2. Всегда ли пользовательский токен действителен только в процессе, вызвавшем OpenProcessToken? Да, дескриптор токена, который вы получили, является индексом в таблице дескрипторов процесса, он не может быть передан напрямую. Вам нужно будет использовать DuplicateHandle, который может быть тем, что вы хотите, но может быть грязным.

  3. Вы хотите найти лучший способ получить токен пользователя для запуска приложения в пользовательском (интерактивном?) сеансе. В этом случае лучший способ — получить токен сеанса пользователя и использовать его. Вы можете ознакомиться с этой статьей. и пример кода, он написан на C#, но его относительно легко перенести на выбранный вами язык.

РЕДАКТИРОВАТЬ: Обновлено для включения Windows 2000. Поскольку вы запускаете службу под учетной записью SYSTEM, она может открыть дескриптор самого процесса (при необходимости процесс может отправить свой идентификатор процесса). Затем он может открыть токен, прикрепленный к этому процессу, продублировать его и использовать полученный токен для запуска (или повторного запуска) целевого приложения.

person Stephen Martin    schedule 07.04.2009
comment
1. Может показаться недостатком дизайна. Дело в том, что служба может захотеть обновить приложение: это может быть даже не то приложение, которое должно быть запущено. 2. Согласен, есть. Вместо этого я попытаюсь создать новый токен. 3. Должно работать на 2000, забыл упомянуть... - person Björn; 07.04.2009
comment
Почему служба не просто вызывает OpenProcessToken и DuplicateTokenEx, вместо того, чтобы процесс отправлял что-то в службу? - person Stephen Martin; 07.04.2009
comment
Разве в этом случае созданный процесс не будет запускаться как локальная система? Если я это сделаю, то с таким же успехом могу вызвать CreateProcess и вообще не беспокоиться о пользовательских токенах. - person Björn; 07.04.2009
comment
Только что увидел редактирование. Это кажется хорошей идеей. Я попробую это, когда мне не удалось создать токен с нуля :) - person Björn; 07.04.2009