我有一个重启某些Windows服务的Delphi应用程序。
如果执行此应用程序的用户具有管理权限(Administrators组成员),则服务重启将成功。
对于普通用户,服务重启将失败。
如果普通用户使用“右键单击”以管理员身份运行,也会成功。 但是,普通用户必须输入管理员用户名和密码。
我想为普通用户解决这个问题。
我的想法是在代码中“冒充用户”,显然冒充本地管理员帐户。
但是,它仍然不起作用。
这是我的代码:
var servRequest = (from srDet in SRDB.ServRequestDetails
from srCustReqRef in srDet.ServRequest.ServReqCustReqRefs
from srOpSys in srDet.ServRequest.ServReqOpSys
from srOpSysDet in srOpSys.ServReqOpSysDetails
//from srPh in srDet.ServRequest.ServReqPhases
//from srTask in srPh.ServReqTasks
where srDet!=null && srCustReqRef.CustRequestID == 1 && srDet.IsActiveRow == true
&& srCustReqRef.ServRequestID == 1 && srOpSysDet.IsActiveRow==true
select new ServReqDTO()
{
ServRequestID = srDet.ServRequestID,
Requestor = srDet.HRUser_Requestor.DisplayName,
RequestorID = srDet.RequestorID,
SubmittedDate = srDet.ServRequest.SubmitDateTime,
ServRequestTypeID = srDet.ServRequestTypeID,
ServRequestType = srDet.ServRequestType.ServRequestTypeVal,
TargetDate = srDet.TargetCompletionDate,
OS = srOpSysDet.OperatingSystem.OperatingSystemVal,
OSID = srOpSysDet.OperatingSystem.OperatingSystemID,
//TaskFollowupDates = srTask.ServReqTaskDetails.Where(i => i.IsActiveRow == true).Select(task => task.TaskFollowUpDate).ToList(),
//TaskEndDates = srTask.ServReqTaskDetails.Where(i => i.IsActiveRow == true).Select(task => task.TaskEndDate).ToList(),
//TaskStartDates = srTask.ServReqTaskDetails.Where(i => i.IsActiveRow == true).Select(task => task.TaskStartDate).ToList(),
NextActionDate = null,
ServReqStatus = srDet.ServReqStatusType.ServReqStatusTypeVal,
ServReqStatusTypeID = srDet.ServRequestTypeID
}).ToList();
我称之为:
function GetCurrUserName: string;
var
Size : DWORD;
begin
Size := MAX_COMPUTERNAME_LENGTH + 1;
SetLength(Result, Size);
if GetUserName(PChar(Result), Size) then
SetLength(Result, Size)
else
Result := '';
end;
function ConnectAs(const lpszUsername, lpszPassword: string): Boolean;
var
hToken : THandle;
begin
Result := LogonUser(PChar(lpszUsername), nil, PChar(lpszPassword), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hToken);
if Result then
Result := ImpersonateLoggedOnUser(hToken)
else
RaiseLastOSError;
end;
服务重启将失败。如果用户以管理员身份运行它(右键单击RunAs),它就可以运行。
模仿本身运作良好。我可以通过获取当前用户名来检查它。但是,为什么它仍然不起作用。看起来用户模拟没有管理员权限。
还有其他模仿吗?
答案 0 :(得分:5)
这是可以预料的。在UAC下,管理员组中的用户会收到筛选的令牌,除非他们通过UAC提升过程。您正在模仿其他用户,但是您没有UAC提升,因此拥有过滤的,降低权限的令牌。
为了执行具有提升权限的代码,在UAC下,您必须通过UAC提升过程。如果你可以避免这样做,那么UAC将毫无意义。
据我所知,你有以下原则选择:
runas
shell动词强制提升,或者确实使用其他机制来安排提升。这将使您完成要避免的UAC对话框。顺便说一句,我注意到您在调用ImpersonateLoggedOnUser
时没有检查错误。