如何使用admin creds运行c#应用程序?

时间:2009-05-27 16:24:36

标签: c# windows-services

我编写了一个C#应用程序,可以在用户被锁定帐户(Active Directory)时解锁用户。应用程序搜索特定OU中的用户,并在ComboBox中列出已锁定的用户。然后从ComboBox中选择该用户并选择解锁。

如果您以管理员身份登录,则效果很好。如果您是普通用户号

我想使用admin creds运行我的应用程序,但在普通用户下也尽可能安全。

我正在阅读那可能是一个Windows服务程序,但我不清楚如何编程我的应用程序进行安装,作为服务运行,并在admin creds下运行。

7 个答案:

答案 0 :(得分:8)

这个应用程序背后的目标让我觉得错误。您基本上是在尝试创建一种允许非管理员用户解锁帐户的方法......这是正常用户无法使用的功能。

答案 1 :(得分:2)

您不必使用Windows服务来执行其他操作。您可以使用模拟以另一个用户身份登录以进行实际切换。这是我发现的一个例子,它使用windows dll“advapi32.dll”登录。

从页面底部抓取示例代码。我不想在这里复制他的代码。

http://csharptuning.blogspot.com/2007/06/impersonation-in-c.html

使用模拟的一个问题是,进行模拟的计算机需要与您模仿的用户位于同一个域中。

答案 2 :(得分:2)

这是我用于在Windows 2000上运行的ASP.NET 2.0网站上进行模拟的类。

示例用法:

if (iu.impersonateValidUser("AdminUserName", "DomainName", "AdminPassword"))
{            
    // Do Something Under Other Users Security Context
    iu.undoImpersonation();
}

就是这样......下面的完整课程。

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;


public class ImpersonateUser
{
    public const int LOGON32_LOGON_INTERACTIVE = 2;
    public const int LOGON32_PROVIDER_DEFAULT = 0;

    WindowsImpersonationContext impersonationContext;

    [DllImport("advapi32.dll")]
    public static extern int LogonUserA(String lpszUserName,
        String lpszDomain,
        String lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        ref IntPtr phToken);
    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int DuplicateToken(IntPtr hToken,
        int impersonationLevel,
        ref IntPtr hNewToken);

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool RevertToSelf();

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern bool CloseHandle(IntPtr handle);

    public bool impersonateValidUser(String userName, String domain, String password)
    {
        WindowsIdentity tempWindowsIdentity;
        IntPtr token = IntPtr.Zero;
        IntPtr tokenDuplicate = IntPtr.Zero;

        if (RevertToSelf())
        {
            if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
                LOGON32_PROVIDER_DEFAULT, 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;
    }

    public void undoImpersonation()
    {
        impersonationContext.Undo();
    }
}

答案 3 :(得分:1)

您似乎想要模仿管理员用户。这是一个article and demo。看起来是用.Net 1写的,但是应该让你入门。另请查看WindowsIdentity课程。

答案 4 :(得分:0)

您无法使用Windows服务(轻松),因为Windows服务无法使用GUI。作为服务执行此操作的唯一方法是安装服务,然后创建一个使用IPC将请求传达给服务的GUI应用程序。但这会打开潜在的漏洞。

如果你在Vista上运行,一个很好的选择是edit the manifest file并添加requireAdministrator。


编辑:

听起来我的第一个建议可能就是你想要的......为此,基本过程是:

  • 使您的应用程序成为Windows服务。 MSDN上有walkthrough of this process
  • 让您的服务响应某种形式的IPC。您可以使用套接字,管道或任何其他形式的通信。该服务将“监听”取消阻止用户的请求,然后执行此操作。
  • 在计算机上安装服务。这将使其以管理员身份运行,并始终保持开启状态。
  • 制作第二个申请作为客户。使用相同的IPC技术与服务器通信。这将发送请求以取消阻止客户端到服务。

然后您可以以普通用户身份运行客户端(因为它只需要与服务通信,它不会执行任何需要权限的操作)。

答案 5 :(得分:0)

我的内部网站点上有一个非常相似的小部件,因此位于不同时区的IT部门成员可以处理密码重置,当西海岸的域管理员不可用时,这些密码重置也会执行帐户解锁。这是一个非常简单的任务,除了我这样做之外......

        using System.DirectoryServices;

        // Impersonate the Admin to Reset the Password / Unlock Account //
        // Change variables below.
        ImpersonateUser iu = new ImpersonateUser();
        if (iu.impersonateValidUser("AdminUserName", "DomainName", "AdminPassword"))
        {
            resetPassword("AdminUserName", "AdminPassword", UserToReset, "NewPassword");
            iu.undoImpersonation();
        }

        // Perform the Reset / Unlock //
        public void resetPassword(string username, string password, string acct, string newpassword)
        {
            string Path = // LDAP Connection String
            string Username = username;
            string Password = password;
            string Domain = "DomainName\\"; // Change to your domain name

            DirectoryEntry de = new DirectoryEntry(Path, Domain + Username, Password, AuthenticationTypes.Secure);

            DirectorySearcher ds = new DirectorySearcher(de);

            ds.Filter = "(&(objectClass=user)(|(sAMAccountName=" + acct + ")))";

            ds.PropertiesToLoad.Add("displayName");
            ds.PropertiesToLoad.Add("sAMAccountName");
            ds.PropertiesToLoad.Add("DistinguishedName");
            ds.PropertiesToLoad.Add("CN");

            SearchResult result = ds.FindOne();

            string dn = result.Properties["DistinguishedName"][0].ToString();

            DirectoryEntry uEntry = new DirectoryEntry("LDAP://" + dn, username, password);

            uEntry.Invoke("SetPassword", new object[] { newpassword });
            uEntry.Properties["LockOutTime"].Value = 0;
            uEntry.CommitChanges();
            uEntry.Close();
        }

我非常同意如果使用不当会导致安全问题,我们会记录每个更改并通过电子邮件发送给域管理员(因此他们在循环中),我们会自动生成密码。这对我们的小型IT部门来说是一个巨大的帮助,因为管理员不再需要在凌晨4点醒来重置密码。

答案 6 :(得分:0)

此代码允许您调用另一个可执行文件并以管理员身份运行。

try
{
   path = path_to_your_executable;

   ProcessStartInfo myProcess = new ProcessStartInfo(path);
   myProcess.Domain = domain;
   myProcess.UserName = username;
   myProcess.Password = password;
   myProcess.UseShellExecute = false;

   Process.Start(myProcess);
}
catch (Exception myException)
{
   // error handling
}

不完全是您正在寻找的,但这是一种可能的解决方案。