You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi ADO如何查询userAccountControl设特定位的AD域用户

Delphi 10.4 ADO访问AD检索userAccountControl特定位标记实现

问题场景

  • 开发环境:Delphi 10.4,使用TADOConnection、TADOCommand组件访问Active Directory数据
  • 核心需求:检索userAccountControl字段设置了特定位标记的用户账户,覆盖「账户已禁用」「下次登录必须更改密码」等常见筛选场景
  • 现有方案缺陷:使用精确值匹配的查询语句,仅能返回userAccountControl完全等于指定值的账户,会遗漏叠加了其他位标记的目标账户。例如下方语句只能返回普通常规禁用用户,无法查出既被禁用、又叠加了密码永不过期、智能卡登录要求等其他标记的用户:
select sAMAccountName,userAccountControl from 'LDAP://DC=AD,DC=LOCAL' where userAccountControl='514'
  • 语法兼容问题:LDAP原生的位匹配规则写法(即PowerShell、VBScript中常用的userAccountControl:1.2.840.113556.1.4.803:=<位值>语法),直接在Delphi ADO查询中使用无法生效。

可用实现方案

方案1:使用ADO LDAP驱动原生支持的按位与查询

ADO访问AD的SQL方言原生支持按位与运算,不需要做精确值匹配,直接在WHERE子句中通过位运算判断特定位是否置位即可,语法规则为:

判断userAccountControl是否设置了目标标记位,使用条件 (userAccountControl & <目标位值>) = <目标位值>

常用场景查询示例:

  1. 筛选所有已禁用的用户账户(禁用标记位值为2)
select sAMAccountName, userAccountControl 
from 'LDAP://DC=AD,DC=LOCAL' 
where objectCategory='user' AND (userAccountControl & 2) = 2
  1. 筛选设置了「密码永不过期」标记的用户(对应标记位值为65536)
select sAMAccountName, userAccountControl 
from 'LDAP://DC=AD,DC=LOCAL' 
where objectCategory='user' AND (userAccountControl & 65536) = 65536
  1. 多标记组合筛选:筛选已禁用、且设置了密码永不过期的用户
select sAMAccountName, userAccountControl 
from 'LDAP://DC=AD,DC=LOCAL' 
where objectCategory='user' AND (userAccountControl & 2) = 2 AND (userAccountControl & 65536) = 65536

补充说明:「下次登录必须更改密码」状态不存储在userAccountControl字段中,该状态通过pwdLastSet字段值为0标识,需要筛选这类用户时,在WHERE条件中追加pwdLastSet=0即可。userAccountControl字段常用标记位对应值如下:

  • 账户已禁用:2(常量名UF_ACCOUNTDISABLE)
  • 账户已锁定:16(常量名UF_LOCKOUT)
  • 密码永不过期:65536(常量名UF_DONT_EXPIRE_PASSWD)
  • 要求智能卡登录:4194304(常量名UF_SMARTCARD_REQUIRED)
  • 域加入计算机信任账户:8192(常量名UF_WORKSTATION_TRUST_ACCOUNT)

方案2:代码层位判断兜底方案

如果遇到ADO驱动版本差异导致上述位运算SQL语法报错,可以先拉取全量用户的基础字段,在Delphi代码层面做位判断,兼容性最强:

  1. 先执行基础查询,拉取所有用户对象的sAMAccountName、userAccountControl、pwdLastSet等需要用到的字段,不要加userAccountControl精确匹配条件
  2. 遍历返回的记录集,对每条记录的字段值做按位判断,核心判断代码参考:
const
  UF_ACCOUNTDISABLE = 2;
  UF_LOCKOUT = 16;
  UF_DONT_EXPIRE_PASSWD = 65536;
var
  uacValue: Integer;
begin
  // 此处省略ADOQuery打开、遍历记录的代码
  uacValue := ADOQuery.FieldByName('userAccountControl').AsInteger;
  // 判断是否设置了账户禁用标记
  if (uacValue AND UF_ACCOUNTDISABLE) = UF_ACCOUNTDISABLE then
  begin
    // 命中禁用账户规则,编写后续业务逻辑
  end;
end;

该方案在用户规模10万以下的域环境中性能完全可用,不会出现明显的查询延迟。

内容的提问来源于stack exchange,提问作者Vlad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 20:33:19