过滤Active Directory中的更改通知:创建、删除、取消删除
本文关键字:删除 创建 取消 通知 Directory Active 过滤 | 更新日期: 2023-09-27 18:12:43
我目前正在使用。net中Active Directory域服务中的更改通知,如本博客所述。这将返回在选定对象(或该对象的子树)上发生的所有事件。我现在想要过滤创建和删除(可能还有取消删除)事件的事件列表。
我想告诉ChangeNotifier类只观察创建/删除/取消删除事件。另一个解决方案是接收所有事件并在我这边过滤它们。我知道在删除对象的情况下,返回的属性列表将包含属性isDeleted
,其值为True
。但是,是否有一种方法可以查看事件是否代表对象的创建?在我的测试中,对于用户对象,usnchanged
的值始终是usncreated+1
,对于ou,两者是相等的,但是在高频ad中可以保证这一点吗?还可以比较更改和修改的时间戳。我怎么知道一个对象是否已被删除?
为了记录,下面是来自博客的代码的主要部分:
public class ChangeNotifier : IDisposable
{
static void Main(string[] args)
{
using (LdapConnection connect = CreateConnection("localhost"))
{
using (ChangeNotifier notifier = new ChangeNotifier(connect))
{
//register some objects for notifications (limit 5)
notifier.Register("dc=dunnry,dc=net", SearchScope.OneLevel);
notifier.Register("cn=testuser1,ou=users,dc=dunnry,dc=net", SearchScope.Base);
notifier.ObjectChanged += new EventHandler<ObjectChangedEventArgs>(notifier_ObjectChanged);
Console.WriteLine("Waiting for changes...");
Console.WriteLine();
Console.ReadLine();
}
}
}
static void notifier_ObjectChanged(object sender, ObjectChangedEventArgs e)
{
Console.WriteLine(e.Result.DistinguishedName);
foreach (string attrib in e.Result.Attributes.AttributeNames)
{
foreach (var item in e.Result.Attributes[attrib].GetValues(typeof(string)))
{
Console.WriteLine("'t{0}: {1}", attrib, item);
}
}
Console.WriteLine();
Console.WriteLine("====================");
Console.WriteLine();
}
LdapConnection _connection;
HashSet<IAsyncResult> _results = new HashSet<IAsyncResult>();
public ChangeNotifier(LdapConnection connection)
{
_connection = connection;
_connection.AutoBind = true;
}
public void Register(string dn, SearchScope scope)
{
SearchRequest request = new SearchRequest(
dn, //root the search here
"(objectClass=*)", //very inclusive
scope, //any scope works
null //we are interested in all attributes
);
//register our search
request.Controls.Add(new DirectoryNotificationControl());
//we will send this async and register our callback
//note how we would like to have partial results
IAsyncResult result = _connection.BeginSendRequest(
request,
TimeSpan.FromDays(1), //set timeout to a day...
PartialResultProcessing.ReturnPartialResultsAndNotifyCallback,
Notify,
request
);
//store the hash for disposal later
_results.Add(result);
}
private void Notify(IAsyncResult result)
{
//since our search is long running, we don't want to use EndSendRequest
PartialResultsCollection prc = _connection.GetPartialResults(result);
foreach (SearchResultEntry entry in prc)
{
OnObjectChanged(new ObjectChangedEventArgs(entry));
}
}
private void OnObjectChanged(ObjectChangedEventArgs args)
{
if (ObjectChanged != null)
{
ObjectChanged(this, args);
}
}
public event EventHandler<ObjectChangedEventArgs> ObjectChanged;
#region IDisposable Members
public void Dispose()
{
foreach (var result in _results)
{
//end each async search
_connection.Abort(result);
}
}
#endregion
}
public class ObjectChangedEventArgs : EventArgs
{
public ObjectChangedEventArgs(SearchResultEntry entry)
{
Result = entry;
}
public SearchResultEntry Result { get; set; }
}
大约五年前,我参与了一个项目的设计审查,该项目开始使用AD更改通知。有人问了和你非常相似的问题。我可以分享我所记得的,我不认为事情从那时起有太大的变化。最后我们切换到DirSync。
似乎不可能仅仅创建&从AD更改通知中删除。我们发现,更改通知会导致对大型目录进行足够多的事件监视,从而导致通知处理出现瓶颈并落后。这个API不是为扩展而设计的,但我记得性能/延迟并不是我们切换的主要原因。
是的,新对象的usn关系通常保持不变,尽管我认为在多dc场景中,您可以为新用户获得usncreated == usnchanged,但我们没有进行广泛的测试,因为…
对我们来说重要的是,更改通知只能在不现实的假设下为您提供可靠的对象创建检测,即您的机器在100%的时间内正常运行!在生产系统中,总有一些情况需要重新启动并赶上或重新同步,我们切换到DirSync,因为它有一种健壮的方式来处理这些场景。
在我们的例子中,如果对象创建失败,它可以在不确定的时间内阻止给新用户发送电子邮件。这显然不太好,我们需要确定。对于AD更改通知,要实现正确的重新同步需要做更多的工作,并且很难进行测试。但对于DirSync来说,它更自然,并且有一个快速恢复机制,通常避免重新同步。为了安全起见,我想我们每天都会触发一次完全的重新同步。
DirSync不像更改通知那样实时,但是通过每分钟发出一次DirSync查询,可以获得~30秒的平均延迟。