如何以编程方式授予虚拟用户对文件夹(或文件)的权限

How to programatically grant a virtual user permission to a folder (or file)

我有一个我写的服务需要部署到一些(大约 1100 台)设备上。所有这些 设备都以普通用户而非管理员身份登录

我可以使用我们的部署软件推出服务,该软件以管理员身份 运行。我们的安全团队不希望此服务在本地系统帐户上 运行(出于显而易见的原因)。我想出的是该服务将安装为本地系统,但随后会将其登录帐户更改为虚拟用户,然后需要访问中的文件夹Program Files (x86).

我发现如果我通过命令行安装服务(使用远程管理员访问),我可以安装服务,但是它不会启动.

当我查看事件日志时,我得到一个 UnauthorizedAccessException 错误。

我怀疑这是因为该服务已经 运行 正在虚拟用户 下运行,该用户无权启动该服务 。那么我该如何解决这个问题呢?

在主要的 class 服务中,我有这个方法,应该可以让用户访问必要的文件夹:

    private void GiveDirectoryAccess(string dir, string user)
    {
        try
        {
            DirectoryInfo directoryInfo = new DirectoryInfo(dir);
            DirectorySecurity ds = directoryInfo.GetAccessControl();
            ds.AddAccessRule(new FileSystemAccessRule(user, FileSystemRights.FullControl,
                InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.NoPropagateInherit, AccessControlType.Allow));
            directoryInfo.SetAccessControl(ds);
        }
        catch (Exception e)
        {
            SimpleLog.Log(e);
            throw;
        }

    }

服务初始化后立即调用:

    public CheckRALVersionService()
    {
        InitializeComponent();
        // Give directory access
        string alhadminPath = System.IO.Path.Combine(pathToFolder, alhadmin);
        GiveDirectoryAccess(alhadminPath, serviceUser);
        string exeName = System.IO.Path.GetFileName(fullExeNameAndPath);
        string tmppath = System.IO.Path.Combine(localdir, tmp);
        SimpleLog.SetLogFile(logDir: tmppath, prefix: "debout." + exeName + "_", extension: "log");
        watcher = new DirectoryWatcher(pathToFolder, alhadmin);
    }

然后,在ProjectInstallerclass中,我在serviceInstaller1_Committed方法中将用户更改为虚拟用户:

    void serviceInstaller1_Committed(object sender, InstallEventArgs e)
    {
        using (ManagementObject service = new ManagementObject(new ManagementPath("Win32_Service.Name='RalConfigUpdate'")))
        {
            object[] wmiParams = new object[11];
            wmiParams[6] = @"NT Service\RalConfigUpdate";
            service.InvokeMethod("Change", wmiParams);
        }
    }

我需要帮助服务来授予访问权限吗?我想做的事都可以在这个服务里完成吗?

提前致谢。

一种选择是授予普通用户启动和停止服务的权限。 微软为此提供了一个小工具:SubInAcl!

Set Windows Service Permission!

应该也可以使用组策略来做到这一点。对于您的用例,这应该是更好的方法。另一方面,SubInAcl 方法更容易为您测试。我找到了一个较旧的描述 here!

严格回答你的问题:

你可以使用 System.Io.File.GetAccessControl to get a FileSecurity Class 可用于修改文件系统的权限。 这些链接显示了一些很好的例子。

但是仅当将运行该过程的用户有权更改Windows的权限时才有效,否则= ===> UnauthorizedAccessException

经过一段时间的思考,我找到了解决方案。它可能不是最优雅的,但它应该适合我的目的。我拥有所有“零件”,但只是按错误的顺序做事。

以前,我试图在安装过程中更改用户,但没有成功。我最终做的是允许该服务安装为 LOCAL SYSTEM 帐户,然后在实际程序的 OnStart 方法期间更改为虚拟帐户用户。

所以:

    protected override void OnStart(string[] args)
    {
        string alhadminPath = System.IO.Path.Combine(pathToFolder, alohadmin);

        try
        {
            // Update the service state to start pending
            ServiceStatus serviceStatus = new ServiceStatus
            {
                dwCurrentState = ServiceState.SERVICE_START_PENDING,
                dwWaitHint = 100000
            };
            SetServiceStatus(this.ServiceHandle, ref serviceStatus);

            // Update the logs
            eventLog1.WriteEntry("Starting Service", EventLogEntryType.Information, eventId++);
            SimpleLog.Info("RAL Config Update Service started");

            serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING;
            SetServiceStatus(this.ServiceHandle, ref serviceStatus);

            // Change the user to the virutal user
            using (ManagementObject service = new ManagementObject(new ManagementPath("Win32_Service.Name='RalConfigUpdate'")))
            {
                object[] wmiParams = new object[11];
                wmiParams[6] = serviceUser;
                service.InvokeMethod("Change", wmiParams);
            }
            GiveDirectoryAccess(alhadminPath, serviceUser);
        }
        catch (Exception e)
        {
            eventLog1.WriteEntry("Service failed to start", EventLogEntryType.Error, eventId++);
            SimpleLog.Log(e);
            throw;
        }
    }

这是正常的工作方式,也应该满足安全程序。谢谢大家。