如何使用管理员凭据更改当前用户的文件夹权限?

Posted

技术标签:

【中文标题】如何使用管理员凭据更改当前用户的文件夹权限?【英文标题】:How to change folders permission to the current user by using admin credentials? 【发布时间】:2013-09-02 20:34:16 【问题描述】:

好的,所以我一直在寻找一段时间,标题几乎解释了我想要做什么。 此外,在代码中硬编码管理员凭据也没有问题。

最初我用 c# 写了一些代码,几乎解决了这个问题:

private void button2_Click(object sender, EventArgs e)
    

        DirectoryInfo myDirectoryInfo = new DirectoryInfo(textBox1.Text);

        DirectorySecurity myDirectorySecurity = myDirectoryInfo.GetAccessControl();
        string User = System.Environment.UserDomainName + "\\" + comboBox1.SelectedItem.ToString();


        myDirectorySecurity.AddAccessRule(new FileSystemAccessRule(User, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Allow));

        //myDirectorySecurity.AddAccessRule(new FileSystemAccessRule(User, FileSystemRights.Write, InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Allow));

        myDirectoryInfo.SetAccessControl(myDirectorySecurity);
        MessageBox.Show("Permissions Altered Successfully" + User);

    

如果我在我已经拥有权限的文件夹上使用它就可以了,但我需要的是一种使用管理员凭据向普通用户没有权限的文件夹授予权限的方法。

后来我尝试用vbscript写一些东西:

    strHomeFolder = "C:\test"
strUser = " DOMAIN\user"

Set WshShell = CreateObject("WScript.Shell")

WshShell.Run "%COMSPEC% /c Echo Y| cacls  "& strHomeFolder & " /e /c /g "& strUser &":F", 2, True

但我找不到传递管理员凭据的方法。 所以最后我写了另一个代码来尝试完成它:

private void button1_Click(object sender, EventArgs e)
    
        try
        
            //string passwordPre = "PASSWORD";
            //char[] passwordChars = passwordPre.ToCharArray();
            //SecureString password = new SecureString();
            //foreach (char c in passwordChars)
            //
            //    password.AppendChar(c);
            //


            ProcessStartInfo p = new ProcessStartInfo(@"D:\\test.vbs");
            //p.UseShellExecute = false;
            //p.UserName = "username";
            //p.Domain = "DOMAIN";

            //p.Password = password;
            Process.Start(p);
        
        catch (Exception ex)
        
            MessageBox.Show(ex.Message);
        
    

这次我只是尝试使用进程传递管理员凭据,但它生成了消息:指定的可执行文件不是此操作系统平台的有效应用程序。

那么,有什么方法可以用来传递凭据吗? (可以是 c# 或 vbscript)。

提前致谢。

【问题讨论】:

【参考方案1】:

模拟将解决您的问题。当您在模拟上下文中执行代码时,放置在该上下文中的逻辑将以模拟用户的特权执行。下面的类从 web.config 文件中获取模拟配置值。您可以从 app.config 或任何源中读取它来修改它。

所需配置

    用户名 密码 域名

模拟类

 public class Impersonator : IDisposable
    
        #region Win32 Advanced API calls

        /// <summary>
        /// Logons the user.
        /// </summary>
        /// <param name="lpszUserName">Name of the LPSZ user.</param>
        /// <param name="lpszDomain">The LPSZ domain.</param>
        /// <param name="lpszPassword">The LPSZ password.</param>
        /// <param name="dwLogOnType">Type of the dw log on.</param>
        /// <param name="dwLogOnProvider">The dw log on provider.</param>
        /// <param name="phToken">The ph token.</param>
        /// <returns></returns>
        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        private static extern int LogonUser(String lpszUserName,
                String lpszDomain,
                String lpszPassword,
                int dwLogOnType,
                int dwLogOnProvider,
                ref IntPtr phToken);

        /// <summary>
        /// Duplicates the token.
        /// </summary>
        /// <param name="hToken">The h token.</param>
        /// <param name="impersonationLevel">The impersonation level.</param>
        /// <param name="hNewToken">The h new token.</param>
        /// <returns></returns>
        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        private static extern int DuplicateToken(IntPtr hToken,
                int impersonationLevel,
                ref IntPtr hNewToken);

        /// <summary>
        /// Reverts to self.
        /// </summary>
        /// <returns></returns>
        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        private static extern bool RevertToSelf();


        /// <summary>
        /// Closes the handle.
        /// </summary>
        /// <param name="handle">The handle.</param>
        /// <returns></returns>
        [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        private static extern bool CloseHandle(IntPtr handle);

        #endregion

        #region Fields

        /// <summary>
        /// Field to hold the impersonation Context
        /// </summary>
        WindowsImpersonationContext impersonationContext;

        /// <summary>
        /// Track whether Dispose has been called.
        /// </summary>
        private bool disposed;

        #region Constants
        /// <summary>
        /// Logon32 Logon Interactive 
        /// </summary>
        public const int INTERACTIVE_NUMBER = 2;

        /// <summary>
        /// Logon32 Provider Default
        /// </summary>
        public const int DEFAULT_NUMBER = 0;

        /// <summary>
        /// Impersonating user name key
        /// </summary>
        public const string ImpersonatingUserNameKey = "ImpersonatingUserName";

        /// <summary>
        /// Impersonating user password key
        /// </summary>
        public const string ImpersonatingPasswordKey = "ImpersonatingUserPassword";

        /// <summary>
        /// Impersonating user domain key
        /// </summary>
        public const string ImpersonatingDomainNameKey = "ImpersonatingDomain";

        #endregion

        #endregion

        #region Construction/Destruction/Initialization

        /// <summary>
        /// Constructor of the impersonator
        /// </summary>
        public Impersonator()
        
            if (!ImpersonateUser(ConfigurationManager.AppSettings[ImpersonatingUserNameKey],
                                    ConfigurationManager.AppSettings[ImpersonatingDomainNameKey],
                                    ConfigurationManager.AppSettings[ImpersonatingPasswordKey]))
            
                //TODO: Log Exception
            
        

        #endregion

        #region Public Methods

        // Implement IDisposable.
        // Do not make this method virtual.
        // A derived class should not be able to override this method.
        public void Dispose()
        
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        

        /// <summary>
        /// Impersonate User with the given user credentials
        /// </summary>
        /// <param name="userName">User Name</param>
        /// <param name="domain">Domain</param>
        /// <param name="password">Password</param>
        /// <returns>True if success, false otherwise</returns>
        private bool ImpersonateUser(String userName, String domain, String password)
        
            WindowsIdentity tempWindowsIdentity;
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;

            if (RevertToSelf())
            
                if (LogonUser(userName, domain, password, INTERACTIVE_NUMBER,
                        DEFAULT_NUMBER, ref token) != 0)
                
                    if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                    
                        tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                        impersonationContext = tempWindowsIdentity.Impersonate();
                        if (impersonationContext != null)
                        
                            CloseHandle(token);
                            CloseHandle(tokenDuplicate);
                            return true;
                        
                    
                
            
            if (token != IntPtr.Zero)
                CloseHandle(token);
            if (tokenDuplicate != IntPtr.Zero)
                CloseHandle(tokenDuplicate);
            return false;
        

        /// <summary>
        /// Undo impersonation
        /// </summary>
        private void StopImpersonation()
        
            impersonationContext.Undo();
        

        #endregion

        #region Protected Methods

        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be disposed.
        // If disposing equals false, the method has been called by the
        // runtime from inside the finalizer and you should not reference
        // other objects. Only unmanaged resources can be disposed.
        protected virtual void Dispose(bool disposing)
        
            // Check to see if Dispose has already been called.
            if (!this.disposed)
            
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if (disposing)
                
                    StopImpersonation();
                

                // Note disposing has been done.
                disposed = true;
            
        

        #endregion
    

如何调用方法

Using(Impersonator impersonator = new Impersonator())

  //Write the folder accessing logic here

【讨论】:

@Guga00 很高兴它帮助了你:)

以上是关于如何使用管理员凭据更改当前用户的文件夹权限?的主要内容,如果未能解决你的问题,请参考以下文章

在没有 Windows 访问权限的情况下使用凭据信息访问共享文件夹

如何更改linux文件目录拥有者及用户组

C# 使用登录的用户凭据启动进程

如何更改文件权限

如何更改linux文件目录拥有者及用户组

win10系统 为啥有完全控制权限也无法消除文件夹只读属性?