如何使用管理员凭据运行 c# 应用程序?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/916714/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 03:09:10  来源:igfitidea点击:

How to run c# application with admin creds?

c#windows-services

提问by

I wrote a C# application that unlocks users when they are locked out of their account (Active Directory). The application searches for users in a specific OU and will list the locked out users in a ComboBox. Then you select that user from the ComboBox and choose unlock.

我编写了一个 C# 应用程序,当用户被锁定在他们的帐户 (Active Directory) 之外时,它会解锁用户。应用程序搜索特定 OU 中的用户,并将在 ComboBox 中列出锁定的用户。然后从 ComboBox 中选择该用户并选择解锁。

If you are logged in as an admin, it works perfect. If you are a normal user no.

如果您以管理员身份登录,它就完美无缺。如果您是普通用户没有。

I want to run my application with admin creds but under a normal user also as secure as possible.

我想使用管理员凭据运行我的应用程序,但在普通用户下也尽可能安全。

I was reading that maybe program a windows service but I'm unclear on how to program my application to install, run as a service, and run under admin creds.

我正在阅读可能会编程 Windows 服务,但我不清楚如何编程我的应用程序以安装、作为服务运行以及在管理员凭据下运行。

采纳答案by Jeremy

Looks like you want to impersonate the admin user. Here's an article and demo. Looks to be written in .Net 1 but should get you started. Also check out the WindowsIdentityclass.

看起来您想模拟管理员用户。这是一篇文章和演示。看起来是用 .Net 1 编写的,但应该可以帮助您入门。另请查看WindowsIdentity类。

回答by Brian

The goal behind this application strikes me as wrong. You are basically trying to create a means of allowing non-admin users to unlock accounts...which is, for good reason, a feature not available to normal users.

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

回答by Reed Copsey

You cannot use a Windows Service (easily), since a Windows Service cannot have a GUI. The only way to do this as a service would be to install the service, and then make a GUI app that used IPC to communicate the request to the service. This would open up a potential loophole, though.

你不能使用 Windows 服务(很容易),因为 Windows 服务不能有 GUI。作为服务执行此操作的唯一方法是安装该服务,然后制作一个 GUI 应用程序,该应用程序使用 IPC 将请求传达给该服务。不过,这会打开一个潜在的漏洞。

If you're running on Vista, a good option would be to edit the manifest fileand add requireAdministrator.

如果您在 Vista 上运行,一个不错的选择是编辑清单文件并添加 requireAdministrator。



Edit:

编辑:

It sounds like my first suggestion may be what you want... To do this, the basic process is:

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

  • Make your application a windows service. There is a walkthrough of this processon MSDN.
  • Make your service respond to some form of IPC. You could use sockets, pipes, or any other form of communication. The service would "listen" for a request to unblock a user, then perform this.
  • Install the service on the machine. This will make it run as an administrator, and just be always on.
  • Make a second application to act as a client. Use the same IPC technology to communicate with the server. This would send the request to unblock the client to the service.
  • 使您的应用程序成为 Windows 服务。MSDN 上有此过程演练
  • 让您的服务响应某种形式的 IPC。您可以使用套接字、管道或任何其他形式的通信。该服务将“侦听”解除阻止用户的请求,然后执行此操作。
  • 在机器上安装服务。这将使其以管理员身份运行,并且始终处于开启状态。
  • 制作第二个应用程序以充当客户端。使用相同的 IPC 技术与服务器进行通信。这会将取消阻止客户端的请求发送到服务。

You could then run the client as a normal user (since it just needs to talk to the service, it does not do anything that requires permissions).

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

回答by Dilbert789

You don't have to use a windows service to do something as someone else. You can use impersonation to login as another user to do the actual switch. Here's an example I found that uses the windows dll "advapi32.dll" to login.

您不必像其他人一样使用 Windows 服务来做某事。您可以使用模拟以其他用户身份登录以进行实际切换。这是我发现的一个使用 windows dll“advapi32.dll”登录的示例。

Grab the sample code off the bottom of the page. I didn't want to just copy his code here.

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

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

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

One cavet with Impersonation though is that the computer doing the impersonation needs to be on the same domain as the user that your impersonating.

不过,与模拟有关的一个警告是,进行模拟的计算机需要与您模拟的用户位于同一域中。

回答by Zachary

I have a very similar widget on my intranet site, so members of the IT department located in different time zones can handle password resets that also performs a account unlock when the domain admins on the west coast are not available. This is a pretty simple tasks and here is an except of how I did this...

我的 Intranet 站点上有一个非常相似的小部件,因此位于不同时区的 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();
        }

I strongly agree that this can lead to security issues if incorrectly used, we have every change logged and emailed to the domain admins (so their in the loop) and we auto generate the passwords. This has been a huge help for our small IT department, since admins no longer have to wake up at 4 AM to reset a password.

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

回答by Ryan Rodemoyer

This code will allow you to call another executable and run it is an administrator.

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

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
}

Not exactly what you're looking for but it is a possible solution.

不完全是你正在寻找的,但它是一个可能的解决方案。

回答by Zachary

Here is the class I use to perform impersonation on a ASP.NET 2.0 website, running on Windows 2000.

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

Example Usage:

示例用法:

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

That's it... Complete class below.

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

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();
    }
}