以编程方式锁定Active Directory帐户

时间:2008-10-07 14:33:00

标签: c# active-directory

我必须在C#中以编程方式锁定Active Directory中的用户帐户。

不幸的是,它不能通过userAccountControl属性工作。每次我将userAccountControl设置为528(=普通帐户w /锁定标志)时,Active Directory将不接受该值并将其重置,而不另行通知512(=普通帐户)。

现在我试图通过提供不正确的凭据来锁定帐户(见下文),但这也不起作用。

int retries = 0;
while (!adsUser.IsAccountLocked && retries < MAX_LOCK_RETRIES)
{
     retries++;

    try
    {  
        new DirectoryEntry(userPath, logonName, incorrectPassword).RefreshCache();
    }
    catch (Exception)
    { 
        /* ... */ 
    }
    adsUser.GetInfo();
}

有什么想法吗?

4 个答案:

答案 0 :(得分:4)

确保您用于停用帐户的帐户具有足够的权限来停用帐户。请参阅Microsoft的this example

答案 1 :(得分:1)

根据您的Active Directory策略,可能需要进行交互式登录尝试才能锁定帐户。您可以使用LogonUser method of advapi32.dll模拟这些模拟。在我的测试中,我已经看到运行此循环100次并不能保证在域控制器上尝试100次密码错误,因此您应该check the user is locked out并在必要时进行更多尝试。

这样做的底线是您应该禁用帐户而不是尝试锁定帐户。有no functional difference between locked and disabled accounts。下面的代码是黑客。

using System;
using System.Runtime.InteropServices;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            IntPtr token = IntPtr.Zero;
            string userPrincipalName = "userID@domain.com";
            string authority = null; // Can be null when using UPN (user principal name)
            string badPassword = "bad";

            int maxTries = 100;
            bool res = false;

            for (var i = 0; i < maxTries; i++)
            {
                res = LogonUser(userPrincipalName, authority, badPassword, LogonSessionType.Interactive, LogonProvider.Default, out token);
                CloseHandle(token);
            }
        }

        [DllImport("advapi32.dll", SetLastError = true)]
        static extern bool LogonUser(
          string principal,
          string authority,
          string password,
          LogonSessionType logonType,
          LogonProvider logonProvider,
          out IntPtr token);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool CloseHandle(IntPtr handle);
        enum LogonSessionType : uint
        {
            Interactive = 2,
            Network,
            Batch,
            Service,
            NetworkCleartext = 8,
            NewCredentials
        }

        enum LogonProvider : uint
        {
            Default = 0, // default for platform (use this!)
            WinNT35,     // sends smoke signals to authority
            WinNT40,     // uses NTLM
            WinNT50      // negotiates Kerb or NTLM
        }
    }
}

答案 2 :(得分:0)

一旦你有目录条目对象,这将有效。

DirectoryEntry de = result.GetDirectoryEntry();
int val = (int)de.Properties["userAccountControl"].Value;
de.Properties["userAccountControl"].Value = val | 0x0002;

答案 3 :(得分:0)

此代码可用于锁定AD中的用户

/// <summary>
/// Locks a user account
/// </summary>
/// <param name="userName">The name of the user whose account you want to unlock</param>
/// <remarks>
/// This actually trys to log the user in with a wrong password. 
/// This in turn will lock the user out
/// </remarks>
public void LockAccount(string userName)
{
    DirectoryEntry user = GetUser(userName);
    string path = user.Path;
    string badPassword = "SomeBadPassword";
    int maxLoginAttempts = 10;

    for (int i = 0; i &lt maxLoginAttempts; i++)
    {
        try
        {
            new DirectoryEntry(path, userName, badPassword).RefreshCache();
        }
        catch (Exception e)
        {

        }
    }
    user.Close();
}