以编程方式锁定Active Directory帐户

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

请确保您使用的账户有足够的权限来禁用账户。请参照微软的示例


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

这对我起作用了。虽然我不得不自己实现方法 GetUser(userName) ,但我结合使用了 pc = PrincipalContext(ContextType.Domain)UserPrincipal.FindByIdentity(pc, userName) 和在结果对象上使用 .GetUnderlyingObject()(强制转换为 DirectoryInfo)。别忘了进行空值检查 ;-) - Gertsen

1
根据您的Active Directory策略,可能需要交互式登录尝试来锁定帐户。 您可以使用advapi32.dll的LogonUser方法进行模拟。 在我的测试中,运行此循环100次不能保证在域控制器上有100个错误密码尝试,因此如果需要,应检查用户是否被锁定并进行更多尝试。
总之,您应该禁用帐户而不是尝试锁定它。 锁定和禁用帐户之间没有功能上的区别。 下面的代码是一个hack。
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
        }
    }
}

0

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

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

这将禁用账户,但不会锁定它。 - KoenVosters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接