[英]Active directory Query to narrow down results better than my attempt
我的特定问题:如何缩小对没有设置employeeNumber属性(不为null或为空)的活动目录帐户的搜索?
我的解决方法是检查结果并检查employeeNumber并删除这些帐户。 但是,我希望查询可以缩小结果范围,然后再手动过滤。
我认为甚至没有触发过滤器的行: ((DirectorySearcher)ps.GetUnderlyingSearcher()).Filter = "(&(objectCategory=Person)(objectClass=User)(!employeeNumber=*))";// I would like for it to return only Ad Accounts that have an employeeNumber set
PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, "myDomain");
UserPrincipal user = new UserPrincipal(domainContext);
user.SamAccountName = ParamSamAccountName;
user.Enabled = true;//only enabled users
user.PasswordNeverExpires = false; //this should get rid of service accounts
PrincipalSearcher pS = new PrincipalSearcher();
pS.QueryFilter = user;
PrincipalSearcher ps = new PrincipalSearcher(user);
((DirectorySearcher)ps.GetUnderlyingSearcher()).PageSize = 500;
((DirectorySearcher)ps.GetUnderlyingSearcher()).Filter = "(&(objectCategory=Person)(objectClass=User)(!(employeeNumber=*)))";//this doesnt seem to be working... bug...
var searchResults = SafeFindAll(ps);
private static IEnumerable<Principal> SafeFindAll(PrincipalSearcher searcher)
{
using (var results = searcher.FindAll())
{
foreach (var result in results)
{
yield return result;
}
} // SearchResultCollection will be disposed here
}
这是我的方法:
1.子类UserPrincipal引入noEmployeeNumber和objectCategory属性( 这是一个很好的示例,对我有很大帮助):
[DirectoryRdnPrefix("CN")]
[DirectoryObjectClass("Person")]
public class UserPrincipalEx : UserPrincipal
{
// Implement the constructor using the base class constructor.
public UserPrincipalEx(PrincipalContext context) : base(context) { }
// Implement the constructor with initialization parameters.
public UserPrincipalEx(PrincipalContext context,
string samAccountName,
string password,
bool enabled)
: base(context, samAccountName, password, enabled)
{ }
// Create the "employeeNumber" property.
[DirectoryProperty("!employeeNumber")]
public bool noEmployeeNumber
{
get
{
if (ExtensionGet("!employeeNumber").Length != 1) return false;
string empNum = (string)ExtensionGet("!employeeNumber")[0];
if (empNum == "*") return true; else return false;
}
set
{
ExtensionSet("!employeeNumber", "*");
}
}
// Create the "objectCategory" property.
[DirectoryProperty("objectCategory")]
public string objectCategory
{
get
{
object[] result = this.ExtensionGet("objectCategory");
if (result != null)
{
return (string)result[0];
}
else
{
return string.Empty;
}
}
set { this.ExtensionSet("objectCategory", value); }
}
// Implement the overloaded search method FindByIdentity.
public static new UserPrincipalEx FindByIdentity(PrincipalContext context, string identityValue)
{
return (UserPrincipalEx)FindByIdentityWithType(context, typeof(UserPrincipalEx), identityValue);
}
// Implement the overloaded search method FindByIdentity.
public static new UserPrincipalEx FindByIdentity(PrincipalContext context, IdentityType identityType, string identityValue)
{
return (UserPrincipalEx)FindByIdentityWithType(context, typeof(UserPrincipalEx), identityType, identityValue);
}
}
2.更改代码以使用新的UserPrincipalEx并将值分配给它的新属性:
PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, "mydomain");
UserPrincipalEx user = new UserPrincipalEx(domainContext);
// here are our new properties:
user.noEmployeeNumber = true;
user.objectCategory = "person";
user.Enabled = true; //only enabled users
user.PasswordNeverExpires = false; //this should get rid of service accounts
PrincipalSearcher ps = new PrincipalSearcher(user);
var searchResults = ps.FindAll();
结果将是未设置employeeNumber属性的所有用户的列表。
您的问题有点令人困惑。 如果您要设置WITHOUTemployeeNumber,那么您是正确的,如果您要设置WITH WITHemployeeNumber,那么您需要:(&(objectCategory = Person)(objectClass = User)(employeeNumber = *))
另外,您需要确保获得LDAP连接。 下面的一些代码可能会有所帮助,另请参见此博客: http : //www.codeproject.com/Articles/18102/Howto-Almost-Everything-In-Active-Directory-via-C#20
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LDAPCSharp
{
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
class Program
{
static void Main(string[] args)
{
var ldapDomain = FriendlyDomainToLdapDomain("domainRemoved");
var allResults = FindAllWithEmployeeNumber(ldapDomain);
foreach (var searchResult in allResults)
{
using (var entry = searchResult.GetDirectoryEntry())
{
foreach (var value in entry.Properties.PropertyNames)
{
Console.WriteLine(value);
}
}
}
}
/// <summary>
/// The find all.
/// </summary>
/// <param name="ldapDomain">
/// The ldap domain.
/// </param>
/// <returns>
/// The <see cref="IEnumerable"/>.
/// </returns>
public static IEnumerable<SearchResult> FindAllWithEmployeeNumber(string ldapDomain)
{
string connectionPrefix = "LDAP://" + ldapDomain;
DirectoryEntry entry = new DirectoryEntry(connectionPrefix);
DirectorySearcher mySearcher = new DirectorySearcher(entry);
// all that have employeenumber set
mySearcher.Filter = "(&(objectCategory=Person)(objectClass=User)(employeeNumber=*))";
// all WITHOUT employeenumber set
// mySearcher.Filter = (&(objectCategory=Person)(objectClass=User)(!(employeeNumber=*)))";
mySearcher.PageSize = 10;
var results = SafeFindAll(mySearcher);
mySearcher.Dispose();
return results;
}
public static string FriendlyDomainToLdapDomain(string friendlyDomainName)
{
string ldapPath = null;
try
{
DirectoryContext objContext = new DirectoryContext(
DirectoryContextType.Domain, friendlyDomainName);
Domain objDomain = Domain.GetDomain(objContext);
ldapPath = objDomain.Name;
}
catch (DirectoryServicesCOMException e)
{
ldapPath = e.Message.ToString();
}
return ldapPath;
}
private static IEnumerable<SearchResult> SafeFindAll(DirectorySearcher searcher)
{
using (var results = searcher.FindAll())
{
foreach (var result in results)
{
yield return (SearchResult)result;
}
} // SearchResultCollection will be disposed here
}
}
}
找到用户的两种方法
var userName = Request.ServerVariables["LOGON_USER"];
var pc = new PrincipalContext(ContextType.Domain);
var userFind = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, userName);
要么
string fullName = null;
using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
{
using (UserPrincipal user = UserPrincipal.FindByIdentity(context,"someUserName"))
{
if (user != null)
{
fullName = user.DisplayName;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.