我可以通过下一行代码检查用户域管理员:
using (Impersonation im = new Impersonation(UserName, Domain, Password))
{
System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent();
bool isDomainAdmin = identity.IsDomainAdmin(Domain, UserName, Password);
if (!isDomainAdmin)
{
//deny access, for example
}
}
其中IsDomainAdmin - 是扩展方法
public static bool IsDomainAdmin(this WindowsIdentity identity, string domain, string userName, string password)
{
Domain d = Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain, domain, userName, password));
using (DirectoryEntry de = d.GetDirectoryEntry())
{
byte[] domainSIdArray = (byte[])de.Properties["objectSid"].Value;
SecurityIdentifier domainSId = new SecurityIdentifier(domainSIdArray, 0);
SecurityIdentifier domainAdminsSId = new SecurityIdentifier(WellKnownSidType.AccountDomainAdminsSid, domainSId);
WindowsPrincipal wp = new WindowsPrincipal(identity);
return wp.IsInRole(domainAdminsSId);
}
}
但是,当调用方法IsDomainAdmin时,它会尝试将一些文件写入%LOCALAPPDATA%以供模拟用户使用,如果程序运行时不是管理员,则会抛出异常
无法加载文件或程序集'System.DirectoryServices, Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a'或 其中一个依赖项。要么假冒级别不是 提供,或提供的模拟级别无效。 (例外 来自HRESULT:0x80070542)
答案 0 :(得分:3)
您当然不需要用户密码来验证用户是否是某个组的成员。那么为什么不使用DirectoryEntry
或DirectorySearcher
直接查询AD?如果您还需要验证提供的密码是否正确,则可以使用PrincipalContext.ValidateCredentials
在附加步骤中执行此操作。 (见PrincipalContext.ValidateCredentials Method (String, String))。
static void Main(string[] args) {
string userDomain = "somedomain";
string userName = "username";
string password = "apassword";
if (IsDomainAdmin(userDomain, userName)) {
string fullUserName = userDomain + @"\" + userName;
PrincipalContext context = new PrincipalContext(
ContextType.Domain, userDomain);
if (context.ValidateCredentials(fullUserName, password)) {
Console.WriteLine("Success!");
}
}
}
public static bool IsDomainAdmin(string domain, string userName) {
string adminDn = GetAdminDn(domain);
SearchResult result = (new DirectorySearcher(
new DirectoryEntry("LDAP://" + domain),
"(&(objectCategory=user)(samAccountName=" + userName + "))",
new[] { "memberOf" })).FindOne();
return result.Properties["memberOf"].Contains(adminDn);
}
public static string GetAdminDn(string domain) {
return (string)(new DirectorySearcher(
new DirectoryEntry("LDAP://" + domain),
"(&(objectCategory=group)(cn=Domain Admins))")
.FindOne().Properties["distinguishedname"][0]);
}
答案 1 :(得分:2)
我们修改了@jmh_gr回答,它似乎独立于"Domain Admins"
组名。
static string BuildOctetString(SecurityIdentifier sid)
{
byte[] items = new byte[sid.BinaryLength];
sid.GetBinaryForm(items, 0);
StringBuilder sb = new StringBuilder();
foreach (byte b in items)
{
sb.Append(b.ToString("X2"));
}
return sb.ToString();
}
public static bool IsDomainAdmin(string domain, string userName)
{
using (DirectoryEntry domainEntry = new DirectoryEntry(string.Format("LDAP://{0}", domain)))
{
byte[] domainSIdArray = (byte[])domainEntry.Properties["objectSid"].Value;
SecurityIdentifier domainSId = new SecurityIdentifier(domainSIdArray, 0);
SecurityIdentifier domainAdminsSId = new SecurityIdentifier(WellKnownSidType.AccountDomainAdminsSid, domainSId);
using (DirectoryEntry groupEntry = new DirectoryEntry(string.Format("LDAP://<SID={0}>", BuildOctetString(domainAdminsSId))))
{
string adminDn = groupEntry.Properties["distinguishedname"].Value as string;
SearchResult result = (new DirectorySearcher(domainEntry, string.Format("(&(objectCategory=user)(samAccountName={0}))", userName), new[] { "memberOf" })).FindOne();
return result.Properties["memberOf"].Contains(adminDn);
}
}
}
无论如何,感谢@jmh_gr的答案。
答案 2 :(得分:0)
使用@lluisfranco的代码
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using System.Net.NetworkInformation;
using System.Security.Principal;
namespace Alpha.Code
{
public static class SecurityExtensions
{
public static bool IsDomainAdmin (this WindowsIdentity identity)
{
Domain d = Domain.GetDomain(new
DirectoryContext(DirectoryContextType.Domain, getDomainName()));
using (DirectoryEntry de = d.GetDirectoryEntry())
{
byte[] bdomSid = (byte[])de.Properties["objectSid"].Value;
string sdomainSid = sIDtoString(bdomSid);
WindowsPrincipal wp = new WindowsPrincipal(identity);
SecurityIdentifier dsid = new SecurityIdentifier(sdomainSid);
SecurityIdentifier dasid = new SecurityIdentifier(
WellKnownSidType.AccountDomainAdminsSid, dsid);
return wp.IsInRole(dasid);
}
}
public static string getDomainName()
{
return IPGlobalProperties.GetIPGlobalProperties().DomainName;
}
public static string sIDtoString(byte[] sidBinary)
{
SecurityIdentifier sid = new SecurityIdentifier(sidBinary, 0);
return sid.ToString();
}
}
}
使用示例:
if (WindowsIdentity.GetCurrent().IsDomainAdmin())
{
//Actions to do if user is domain admin
}