我目前正在使用 Change Notifications in Active Directory Domain Services在 .NET 中,如所述 in this blog 。这将返回选定对象(或该对象的子树)上发生的所有事件。我现在想要过滤创建和删除(可能还包括取消删除)事件的事件列表。
我想告诉 ChangeNotifier 类仅观察创建/删除/取消删除事件。另一个解决方案是接收所有事件并在我这边过滤它们。我知道,在删除对象的情况下,返回的属性列表将包含属性 isDeleted
,其值为 True
。但是有没有办法查看该事件是否代表对象的创建?在我的测试中,对于用户对象,usnchanged
的值始终为 usncreated+1
,并且对于 OU 来说两者相等,但是在高频 AD 中可以保证这一点吗?还可以比较更改和修改的时间戳。我如何判断对象是否已被取消删除?
仅供记录,这里是代码的主要部分from the blog :
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% 运行的不切实际的假设下为您提供可靠的对象创建检测!在生产系统中,总有一些情况需要重新启动并 catch 或重新同步,我们切换到 DirSync,因为它有一种强大的方法来处理这些情况。
在我们的例子中,如果错过了对象创建,它可能会在不确定的时间内阻止向新用户发送电子邮件。这显然不好,我们需要确定。对于 AD 更改通知,正确重新同步需要更多工作并且难以测试。但对于 DirSync 来说,它更自然,并且有一个快速路径恢复机制,通常可以避免重新同步。为了安全起见,我认为我们每天都会触发一次完全重新同步。
DirSync 不像更改通知那么实时,但通过每分钟发出一次 DirSync 查询可以获得大约 30 秒的平均延迟。
关于c# - Active Directory 中的过滤器更改通知 : Create, 删除、取消删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24735828/