简体   繁体   English

如何检查[UserName]和[Password]的用户是否是[DomainName]的域管理员而没有模拟?

[英]How to check if user with [UserName] and [Password] is domain administrator of [DomainName] without impersonation?

Impersonation example 模拟示例

I can check is user domain administrator with next lines of code: 我可以检查用户域管理员的下一行代码:

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
    }
}

where IsDomainAdmin - is extension method 其中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);
    }
}

But, when method IsDomainAdmin is called, it is trying to write some files to the %LOCALAPPDATA% for impersonated user, and if program is runnig not as administrator, it throws an exception 但是,当调用方法IsDomainAdmin时,它会尝试将一些文件写入%LOCALAPPDATA%以供模拟用户使用,如果程序运行时不是管理员,则会抛出异常

Could not load file or assembly 'System.DirectoryServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. 无法加载文件或程序集'System.DirectoryServices,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a'或其依赖项之一。 Either a required impersonation level was not provided, or the provided impersonation level is invalid. 未提供所需的模拟级别,或者提供的模拟级别无效。 (Exception from HRESULT: 0x80070542) (HRESULT异常:0x80070542)

You certainly don't need a user's password to verify if the user is a member of a group. 您当然不需要用户的密码来验证用户是否是组的成员。 So why don't you just query AD in a straight-forward manner using DirectoryEntry or DirectorySearcher ? 那你为什么不用DirectoryEntryDirectorySearcher直接查询AD呢? If you also need to verify that the password supplied is correct you can do that in an additional step using PrincipalContext.ValidateCredentials . 如果您还需要验证提供的密码是否正确,则可以使用PrincipalContext.ValidateCredentials在附加步骤中执行此操作。 (See PrincipalContext.ValidateCredentials Method (String, String) ). (请参阅PrincipalContext.ValidateCredentials方法(字符串,字符串) )。

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]);
}

We are modified @jmh_gr answer, and it seems to become independent from "Domain Admins" group name. 我们修改了@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);
        }
    }
}

Anyway, thanks to @jmh_gr for the answer. 无论如何,感谢@jmh_gr的答案。

Using this code by @lluisfranco 使用@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();
        }
    }
}

Usage sample: 使用范例:

if (WindowsIdentity.GetCurrent().IsDomainAdmin())
{
    //Actions to do if user is domain admin
}

Source: 资源:
http://geeks.ms/blogs/lfranco/archive/2009/11/25/how-to-191-como-saber-si-el-usuario-actual-es-administrador-del-dominio.aspx http://geeks.ms/blogs/lfranco/archive/2009/11/25/how-to-191-como-saber-si-el-usuario-actual-es-administrador-del-dominio.aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何获取当前用户的用户名,密码和域 - How to get username, password and domain of current user 检查用户名和密码的类型是客户端还是管理员 - Check if for username and password the type is for a client or for a administrator 用户“ DomainName \\ Username”的登录失败 - Login fail for user 'DomainName\Username' 如何使用用户名和密码以管理员身份运行app - How to run app as administrator using username and password 为用户模拟存储密码 - Storing a password for user impersonation 客户端/服务器应用程序,如何在不将用户名/密码传输到远程系统的情况下,以域用户身份在远程系统上创建进程? - Client/Server app, how to create process on remote system as a domain user without transferring that users username/password to the remote system? 如何检查用户是否是该计算机上的管理员 - How to check if user is an administrator on that machine 如何在不登录的情况下检查用户域名 - How to check domain name of user without logging in 如何在asp.net mvc域名/用户名中进行路由,这样每个用户都有像facebook这样的“用户名” - How to make routing in asp.net mvc domainname/username so each user has his “username” like facebook does 检查当前用户是否为管理员 - Check if the current user is administrator
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM