Этот код отлично работает для получения номера телефона из Active Directory с использованием имени пользователя и пароля.
public string GetPhone(string domain, string username, string pwd)
{
_path = "LDAP://" + domain;
string domainAndUsername = domain + @"\" + username;
DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd);
string telephoneNumber = string.Empty;
try
{
object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
SearchResult result = search.FindOne();
var myEntry = result.GetDirectoryEntry();
telephoneNumber = myEntry.Properties["telephoneNumber"].Value.ToString();
}
catch (Exception ex)
{
throw new Exception("Error obtaining phone number. " + ex.Message);
}
return telephoneNumber;
}
Однако у меня есть доступ к паролю пользователя только на странице входа. У меня есть созданный пользовательский контекст, хотя он доступен из любого места в приложении (Context.User
, который имеет тип System.Security.Principal.IPrincipal
)
Таким образом, как я могу получить телефон из Active Directory, используя уже имеющийся объект Context.User
?
заранее большое спасибо
Это .NET Framework
насколько я помню, может быть, использовать учетную запись администратора для запроса свойства пользователя вместо использования учетной записи пользователя для прямого запроса?
Полученный объект User
будет иметь SID пользователя. При этом вы можете использовать путь LDAP привязки SID в DirectoryEntry
: LDAP://<SID=XXXXX>
var user = new DirectoryEntry(
$"LDAP://<SID = {((WindowsIdentity) HttpContext.User.Identity).User.Value}>");
user.RefreshCache(new [] { "telephoneNumber" });
var telephoneNumber = user.Properties["telephoneNumber"]?.Value as string;
Использование RefreshCache
заключается в загрузке Только атрибута telephoneNumber
. В противном случае, когда вы впервые используете .Properties
, он получит атрибут каждый, что является пустой тратой времени и полосы пропускания.
Получение ссылки на объект System.NullReferenceException, не установленной на экземпляр объекта в первой строке :-(
Используйте отладчик и проверьте, какое значение равно null. Это могут быть HttpContext
, HttpContext.User
, HttpContext.User.Identity
и т. д.
На самом деле это было из-за того, что пользователь не был аутентифицирован, теперь я получаю System.InvalidCastException: «Невозможно преобразовать объект типа «System.Security.Principal.GenericIdentity» в тип «System.Security.Principal.WindowsIdentity» :-(
Используете ли вы проверку подлинности Windows? Или вы использовали аутентификацию с помощью форм?
Использование активного каталога для аутентификации, таким образом, помещая корпоративную учетную запись Windows в логин для веб-сайта.
Приступил к работе!!! Но немного изменил ваш код var winIdentity = System.Security.Principal.WindowsIdentity.GetCurrent(); var user = new DirectoryEntry($"LDAP://<SID = {winIdentity.User.Value}>");
WindowsIdentity.GetCurrent()
получит пользователя, под которым запущено приложение, который может отличаться от пользователя, вошедшего на ваш сайт. Вероятно, он работает на вашем компьютере для разработки, потому что он работает под управлением IIS Express, который работает с вашими учетными данными. Но при развертывании на сервере WindowsIdentity.GetCurrent()
предоставит вам учетные данные пула приложений IIS, что бесполезно.
Похоже, вы используете аутентификацию с помощью форм, где пользователь должен ввести свое имя пользователя и пароль, верно? Мой ответ будет работать только с проверкой подлинности Windows. Поэтому вам придется сделать это по-другому, но это зависит от того, как вы это реализовали. HttpContext.User.Identity.Name
дает вам имя пользователя?
Действительно, вы правы, мое приложение не удалось после развертывания :-( System.Web.HttpContext.Current.User.Identity.Name у меня работает
Все еще борюсь, просто чтобы дать вам больше информации, я пытаюсь получить телефон во время единого входа
Что вы подразумеваете под "единым входом"?
Может быть, я неправильно называю вещи, но в нашем приложении логин обходится, и пользователь входит в систему за кулисами, а не через логин.
Это похоже на проверку подлинности Windows. Вы должны увидеть тег <windowsAuthentication ...>
в вашем файле web.config. Итак, вернитесь к моему второму комментарию выше и проверьте, какое значение равно нулю.
Похоже, я все усложнил, а решение довольно простое.
private void SetPhone()
{
DirectoryEntry entryDomain = new DirectoryEntry("LDAP://" + domain);
DirectorySearcher ds = new DirectorySearcher(entryDomain);
string lastName = Context.User.Identity.Name.Split(' ')[Context.User.Identity.Name.Split(' ').Length - 1];
ds.Filter = "(sn = " + lastName + ")";
SearchResult sr = ds.FindOne();
string telephoneNumber = sr.Properties["telephoneNumber"][0].ToString();
telephoneNumber = telephoneNumber.Insert(0, "(").Insert(4, ")").Insert(5, " ").Insert(9, "-");
Session["UserPhone"] = String.Format("{0:(###) ###-####}", telephoneNumber); ;
}
Я предполагаю, что это ASP.NET, но .NET Framework или Core?