#c# #.net #windows #active-directory
#c# #.net #Windows #active-directory
Вопрос:
Я создаю веб-приложение, которое подключается к Active Directory и позволяет пользователям редактировать свои собственные данные в Active Directory из приложения.
Пользователи могут видеть сведения о других пользователях, поэтому приложение использует проверку подлинности Windows, чтобы разрешить редактирование только собственных данных пользователя. Очевидно, что я не могу предоставить каждому пользователю права администратора, чтобы разрешить это, поэтому при настройке записи каталога я передаю ему учетные данные для учетной записи службы администратора.
После достижения фиксации изменений я вижу, что учетные данные ADEntry верны. Однако, похоже, что он не использует переданные учетные данные, а вместо этого использует учетные данные для проверки подлинности Windows.
Когда пользователь-администратор запускает приложение, он может изменять детали, но когда пользователь, не являющийся администратором, запускает приложение, он получает сообщение об ошибке — доступ запрещен — при достижении CommitChanges() . Это наводит меня на мысль, что он использует учетные данные для проверки подлинности Windows, а не те, которые указаны в DirectoryEntry (учетные данные)
Есть идеи? Нужно ли мне использовать олицетворение?
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 = "(amp;(objectClass=user)(sAMAccountname=" userToFind "))";
searchResult = ADS.FindOne();
return searchResu<
}
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. Вы показываете
ADEntry
, что они создаются и возвращаются изusing
блока.using
Блок будет удаленADEntry
при выходе из этой области. Я думаю, что пример кода немного сбивает с толку. Не могли бы вы немного почистить ее, чтобы лучше показать порядок операций?2. Извинения, в то время у меня были только скопированные фрагменты кода, теперь это должно иметь больше смысла. Ошибка возникает в _ADEntry.CommitChanges() при вызове setProperty, но только при входе в систему проверки подлинности Windows как не-администратор
3. Hrm … все еще немного смущен первыми двумя «методами»,
ADEntry
иADSearcher
. Предполагается, что это методы или они должны представлять класс / конструктор?GetADSearchResult
Методnew
их вводит. Спрашиваю, потому что это все еще не проясняет мою озабоченность тем, что вы используете экземпляр после того, как он был удаленusing
блоком.4. Это то, что я получаю за попытку закодировать в блокноте, поскольку в данный момент у меня нет доступа к моей рабочей станции. Это методы, «новый» в GetADSearchResult был опечаткой, отредактирован. Блок using не должен вызывать проблем, поскольку, когда я прерываю setProperty, _ADEntry имеет правильные myDomain, myAdminServiceUsername и myAdminServicePassword, которые задаются в ADEntry() . Я также могу извлекать сведения из Active Directory, используя те же методы.
5. Другими словами, запись каталога, созданная в ADEntry () и Searcher в ADSearcher (), доступна, отображая правильную информацию, из других методов
Ответ №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 = "(amp;(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 = "(amp;(objectClass=user)(sAMAccountname=" userToFind "))";
var searchResult = directorySearcher.FindOne();
К сожалению, у меня нет AD, доступного для тестирования, и возможно, что это не основная причина вашей проблемы. Тем не менее, я бы рекомендовал исправить код, чтобы не использовать экземпляры объектов после их удаления. Лучшим подходом может быть следующее:
SearchResult searchResu<
using (var directoryEntry = new DirectoryEntry(myDomain, myAdminServiceUsername, myAdminServicePassword, AuthenticationTypes.Secure))
using (var directorySearcher = new DirectorySearcher(directoryEntry))
{
directorySearcher.Filter = "(amp;(objectClass=user)(sAMAccountname=" userToFind "))";
searchResult = directorySearcher.FindOne();
}
// It's OK to use searchResult here, it's not `IDisposable`.
Комментарии:
1. Не будет ли перевод
var directoryEntry = new DirectoryEntry(myDomain, myAdminServiceUsername, myAdminServicePassword, AuthenticationTypes.Secure); var de = directoryEntry; directoryEntry.Dispose();
, хотя даже тогда я все еще не уверен, стоит ли его использоватьusing
2.
var directorySearcher = = new DirectorySearcher(de); ds = directorySearcher; directorySearcher.Dispose(); ds.Filter = "(amp;(objectClass=user)(sAMAccountname=" userToFind "))"; var searchResult = directorySearcher.FindOne();
3. Не уверен, изменит ли это ошибку, но стоит попробовать, это единственное предложение, которое я нашел в результате поиска в течение дня, так что стоит попробовать
4. @KieranJack Нет, это ничего не меняет. Оба
directoryEntry
и вашиde
ссылки указывают на один и тот же экземпляр объекта. Один экземпляр все еще удаляется. Присвоение объекта другой переменной не выполняет никакого копирования объекта!5. По моему опыту, удаление объектов or обычно не имеет никакого значения
DirectoryEntry
DirectorySearcher
. Исключение составляет, если вы перебираете тысячи учетных записей; у сборщика мусора нет времени наверстать упущенное, поэтому удаление объектов помогает снизить потребление памяти. Кроме того, всегда удаляйтеSearchResultCollection
при использованииDirectorySearcher.FindAll()
(см. Раздел «Примечания»)