过滤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; }
}

过滤Active Directory中的更改通知:创建、删除、取消删除

大约五年前,我参与了一个项目的设计审查,该项目开始使用AD更改通知。有人问了和你非常相似的问题。我可以分享我所记得的,我不认为事情从那时起有太大的变化。最后我们切换到DirSync。

似乎不可能仅仅创建&从AD更改通知中删除。我们发现,更改通知会导致对大型目录进行足够多的事件监视,从而导致通知处理出现瓶颈并落后。这个API不是为扩展而设计的,但我记得性能/延迟并不是我们切换的主要原因。

是的,新对象的usn关系通常保持不变,尽管我认为在多dc场景中,您可以为新用户获得usncreated == usnchanged,但我们没有进行广泛的测试,因为…

对我们来说重要的是,更改通知只能在不现实的假设下为您提供可靠的对象创建检测,即您的机器在100%的时间内正常运行!在生产系统中,总有一些情况需要重新启动并赶上或重新同步,我们切换到DirSync,因为它有一种健壮的方式来处理这些场景。

在我们的例子中,如果对象创建失败,它可以在不确定的时间内阻止给新用户发送电子邮件。这显然不太好,我们需要确定。对于AD更改通知,要实现正确的重新同步需要做更多的工作,并且很难进行测试。但对于DirSync来说,它更自然,并且有一个快速恢复机制,通常避免重新同步。为了安全起见,我想我们每天都会触发一次完全的重新同步。

DirSync不像更改通知那样实时,但是通过每分钟发出一次DirSync查询,可以获得~30秒的平均延迟。