3

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

不幸的是,它不能通过 userAccountControl 属性起作用。每次我将 userAccountControl 设置为 528(=带有锁定标志的普通帐户)时,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

4 回答 4

4

确保您用于禁用帐户的帐户具有足够的权限来禁用帐户。请参阅Microsoft 的此示例

于 2008-10-07T14:39:56.897 回答
2

此代码将用于锁定 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();
}
于 2011-10-28T14:53:51.890 回答
1

根据您的 Active Directory 策略,可能需要交互式登录尝试来锁定帐户。您可以使用LogonUseradvapi32.dll 的方法模拟那些。在我的测试中,我发现运行此循环 100 次并不能保证在域控制器上尝试 100 次错误密码,因此您应该检查用户是否被锁定并在必要时进行更多尝试。

这样做的底线是您应该禁用帐户而不是尝试锁定它。锁定帐户和禁用帐户之间没有功能差异。下面的代码是一个黑客。

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
        }
    }
}
于 2015-02-17T16:01:09.773 回答
0

一旦您拥有目录条目对象,这将起作用。

DirectoryEntry de = result.GetDirectoryEntry();
int val = (int)de.Properties["userAccountControl"].Value;
de.Properties["userAccountControl"].Value = val | 0x0002;
于 2011-06-17T18:16:01.460 回答