传入的目录条目凭据未用于提交更改

时间:2019-04-11 17:22:29

标签: c# .net windows active-directory

我正在创建一个连接到Active Directory的Web应用程序,并允许用户从该应用程序在Active Directory中编辑自己的详细信息。

用户可以看到其他用户的详细信息,因此该应用程序使用Windows身份验证仅允许编辑用户自己的详细信息。显然,我无法为每个用户提供Admin特权,因此在设置目录项时,我会向其传递管理服务帐户的凭据。

完成提交更改后,我可以看到ADEntry凭据正确。但是,它似乎没有使用传入的凭据,而是使用Windows身份验证凭据。

当管理员用户运行应用程序时,他们可以更改详细信息,但是当非管理员用户运行应用程序时,他们会收到错误-访问被拒绝-到达CommitChanges()时。这使我相信它使用的是Windows身份验证凭据,而不是DirectoryEntry(credentials)中提供的凭据。

有什么想法吗? 我需要使用模拟吗?

DirectoryEntry ADEntry()
{
    using (DirectoryEntry ADEntry = new DirectoryEntry(myDomain, myAdminServiceUsername, myAdminServicePassword, AuthenticationTypes.Secure))

        {
            return ADEntry;
        }
}

DirectorySearcher ADSearcher()
{
    using(DirectorySearcher ADSearcher = new DirectorySearcher(ADEntry()))
    {
        return ADSearcher;
    }
}

SearchResult GetADSearchResult(string userToFind)
{
    SearchResult searchResult = new SearchResult();
    DirectorySearcher ADS = ADSearcher();
    ADS.Filter = "(&(objectClass=user)(sAMAccountname=" + userToFind + "))";
    searchResult = ADS.FindOne();
    return searchResult;
}

void SetProperty(string userToFind, string propertyToChange, string newPropertyValue)
{
    SearchResult searchResult = GetADSearchResult(userToFind);
    DirectoryEntry _ADEntry = searchResult.GetDirectoryEntry();
    if (_ADEntry.Properties.Contains(propertyToChange))
    {  
        _ADEntry.Properties[propertyToChange].Remove(_ADEntry.Properties[propertyToChange].Value);
    }
    _ADEntry.Properties[propertyToChange].Insert(0, newPropertyValue);
    _ADEntry.CommitChanges();
}

1 个答案:

答案 0 :(得分:1)

这些方法正在创建,立即处理,然后返回一些对象实例:

DirectoryEntry ADEntry()
{
    using (DirectoryEntry ADEntry = new DirectoryEntry(myDomain, myAdminServiceUsername, myAdminServicePassword, AuthenticationTypes.Secure))
    {
        return ADEntry;
    }
}

DirectorySearcher ADSearcher()
{
    using(DirectorySearcher ADSearcher = new DirectorySearcher(ADEntry()))
    {
        return ADSearcher;
    }
}

所以这个:

...
DirectorySearcher ADS = ADSearcher();
ADS.Filter = "(&(objectClass=user)(sAMAccountname=" + userToFind + "))";
searchResult = ADS.FindOne();
...

...可以有效地翻译为:

var directoryEntry = new DirectoryEntry(myDomain, myAdminServiceUsername, myAdminServicePassword, AuthenticationTypes.Secure);
directoryEntry.Dispose();

var directorySearcher = = new DirectorySearcher(directoryEntry);
directorySearcher.Dispose();

directorySearcher.Filter = "(&(objectClass=user)(sAMAccountname=" + userToFind + "))";
var searchResult = directorySearcher.FindOne();

不幸的是,我没有可用的广告来进行测试,这很可能不是问题的根本原因。但是,我建议修复代码,使其在处置对象实例后不使用它们。以下可能是更好的方法:

SearchResult searchResult;
using (var directoryEntry = new DirectoryEntry(myDomain, myAdminServiceUsername, myAdminServicePassword, AuthenticationTypes.Secure))
using (var directorySearcher = new DirectorySearcher(directoryEntry))
{
    directorySearcher.Filter = "(&(objectClass=user)(sAMAccountname=" + userToFind + "))";
    searchResult = directorySearcher.FindOne();
}

// It's OK to use searchResult here, it's not `IDisposable`.