简体   繁体   English

验证C#中的远程Active Directory用户

[英]Validate users of Remote Active Directory in C#

I try to authenticate users belonging to remote ActiveDirectory from my machine, which is not the same domain as the current machine or user domain. 我尝试从我的计算机认证属于远程ActiveDirectory的用户,该计算机与当前计算机或用户域不是同一域。 There will be no trust between my machine and remote ActiveDirectory machine. 我的机器和远程ActiveDirectory机器之间将不信任。

Initial Try 初步尝试

I tried to authenticate a user(Input: sAMAccountName, machine's ipaddress, machine's domain username("Administrator") and machine's password(***). Able to get result that the user with 'sAMAccountName' do exist in ActiveDirectory. 我尝试对用户进行身份验证(输入:sAMAccountName,计算机的ipaddress,计算机的域用户名(“管理员”)和计算机的密码(***)。能够得到具有“ sAMAccountName”的用户确实存在于ActiveDirectory中的结果。

My Requirement : 我的要求

  1. Imagine that already a user("qwerty") is created in ActiveDirectory 想象一下已经在ActiveDirectory中创建了一个用户(“ qwerty”)

  2. From my local machine, I will have the following information, 在本地计算机上,我将获得以下信息,

    a. 一种。 Remote ActiveDirectory ipaddress 远程ActiveDirectory ipaddress

    b. b。 Remote ActiveDirectory machine's username and password. 远程ActiveDirectory计算机的用户名和密码。

    c. C。 Username and password of User "qwerty" 用户“ qwerty”的用户名和密码

  3. I need to check whether User "qwerty" is present in remote ActiveDirectory's users list and validate whether the password entered is same in ActiveDirectory's Users list 我需要检查远程ActiveDirectory的用户列表中是否存在用户“ qwerty”,并验证输入的密码在ActiveDirectory的“用户”列表中是否相同

Code I tried: 我试过的代码:

        DirectoryEntry entry = new DirectoryEntry("LDAP://ipaddress/DC=dinesh,DC=com", name, password);
        DirectorySearcher searcher = new DirectorySearcher(entry);
        searcher.Filter = "(sAMAccountName=" + name + ")";

        try
        {
            SearchResult adsSearchResult = adsSearcher.FindOne();
            isValid = true;
            adsEntry.Close();
        }
        catch (Exception ex)
        {
            adsEntry.Close();
        }

Do I need to create a trust between local machine and remote ActiveDirectory machine before validating Users in a remote ActiveDirectory? 在验证远程ActiveDirectory中的用户之前,是否需要在本地计算机和远程ActiveDirectory计算机之间创建信任关系? If yes please tell how it can be done; 如果是,请说明如何完成;

After creating trust, how can I validate Users? 建立信任后,如何验证用户?

=========================================================================== ================================================== ========================

I am able to use the solution suggested by Rainer, but with a new problem. 我可以使用Rainer建议的解决方案,但是有一个新问题。 When I create a new user via C# code from a different machine, then some properties do not set properly. 当我通过另一台计算机上的C#代码创建新用户时,某些属性设置不正确。 创建用户时未设置属性

Does this need to be set compulsorily while creating user? 创建用户时是否需要强制设置此设置?

First some basics (independent of this question) 首先是一些基础知识(独立于此问题)

Authentication 认证方式

The system checks if Bob is really Bob. 系统检查鲍勃是否真的是鲍勃。 In an Active Directory environment, this is usually done with a domain login from the workstation, Bob enters his username and password, and he gets a Kerberos ticket. 在Active Directory环境中,通常是通过从工作站登录域来完成的,Bob输入用户名和密码,然后获得Kerberos票证。 Later, if he wants to access eg a file share on a remote fileserver, he does not need to login anymore, and can access the files without entering username/password. 以后,如果他想访问例如远程文件服务器上的文件共享,则无需再登录,并且无需输入用户名/密码即可访问文件。

Authorization 授权书

The system checks which resources Bob is allowed to access. 系统检查Bob允许访问哪些资源。 Usually Bob is in domain groups, and a group is in the ACL (access control list) of the resource. 通常,Bob在域组中,而一个组在资源的ACL(访问控制列表)中。

If there are multiple trusting domains, Bob needs to login in one domain, and can access resources in all other domains. 如果存在多个信任域,则Bob需要登录一个域,并且可以访问所有其他域中的资源。 This is one of the main reasons using Active Directory: single sign on 这是使用Active Directory的主要原因之一:单点登录

Checking if user / password is valid 检查用户名/密码是否有效

If you have a username and password and want to check if the password is valid, you have to do a login to the domain. 如果您具有用户名和密码,并且想要检查密码是否有效,则必须登录到域。 There is no way of just “checking if the password is correct”. 没有办法只是“检查密码是否正确”。 Login means: if there is a security policy “lock account if more than 3 invalid logins”, the account will be locked out checking with wrong password, even if you “only want to check the user+password”. 登录是指:如果有一个安全策略“如果无效登录超过3次,则锁定帐户”,即使您“仅想检查用户名+密码”,该帐户也会被锁定并使用错误的密码进行检查。

Using .NET Directory Service functions 使用.NET目录服务功能

I assume here that the process is either run by a human account as a normal program, or the program is a Windows service or a scheduled task which runs under a domain “technical user” account. 我在这里假定该过程是由人工帐户作为普通程序运行的,或者该程序是Windows服务或在“技术用户”帐户域下运行的计划任务。 In this case, you do not need to provide credentials for using the AD functions. 在这种情况下,您无需提供使用AD功能的凭据。 If accessing other trusting AD domains, this is also true. 如果访问其他信任的AD域,则也是如此。 If you want to login to a “foreign domain”, and there is no trust, you need to provide a username+password (as in your code). 如果要登录到“外部域”,并且不信任,则需要提供用户名和密码(如代码中所示)。

"Manually" authenticating a user “手动”认证用户

Normally, this should not be needed. 通常,这不需要。 Example: ASP.NET intranet usage. 示例:ASP.NET Intranet使用情况。 The user access a web application on the current domain or trusting domain, the authentication is done “in the background” by browser and IIS (if integrated Windows authentication is on). 用户访问当前域或信任域上的Web应用程序,身份验证是通过浏览器和IIS在“后台”完成的(如果启用了集成Windows身份验证)。 So you never need to handle user passwords in the application. 因此,您无需在应用程序中处理用户密码。

I don't see many use cases where a password is handled by code. 我看不到用代码处理密码的许多用例。

One may that your program is a helper tool for storing emergency user accounts/passwords. 您的程序可能是用于存储紧急用户帐户/密码的帮助工具。 And you want to check periodically if these accounts are valid. 您想定期检查这些帐户是否有效。

This is a simple way to check: 这是检查的简单方法:

using System.DirectoryServices.AccountManagement;
...

PrincipalContext principalContext = 
     new PrincipalContext(ContextType.Domain, "192.168.1.1");

bool userValid = principalContext.ValidateCredentials(name, password);

One can also use the older, raw ADSI functions: 您还可以使用较早的原始ADSI函数:

using System.DirectoryServices;
....

bool userOk = false;
string realName = string.Empty;

using (DirectoryEntry directoryEntry = 
   new DirectoryEntry"LDAP://192.168.1.1/DC=ad,DC=local", name, password))
{
    using (DirectorySearcher searcher = new DirectorySearcher(directoryEntry))
    {
        searcher.Filter = "(samaccountname=" + name + ")";
        searcher.PropertiesToLoad.Add("displayname");

        SearchResult adsSearchResult = searcher.FindOne();

        if (adsSearchResult != null)
        {
            if (adsSearchResult.Properties["displayname"].Count == 1)
            {   
                realName = (string)adsSearchResult.Properties["displayname"][0];
            }
            userOk = true;
        }
    }
}   

If your real requirement is actually a validity check of user+password, you can do it in one of these ways. 如果您的真正要求实际上是对用户+密码的有效性检查,则可以通过以下方式之一进行。

However, if it is a "normal application", which just wants to check if the entered credentials are valid, you should rethink your logic. 但是,如果它是一个“普通应用程序”,只想检查输入的凭据是否有效,则应重新考虑您的逻辑。 In this case, you better should rely on the single sign on capabilities of AD. 在这种情况下,您最好应该依靠AD的单点登录功能。

If there are further questions, please comment. 如果还有其他问题,请发表评论。

b. b。 Remote ActiveDirectory machine's username and password. 远程ActiveDirectory计算机的用户名和密码。

This sounds a bit unclear. 这听起来有点不清楚。 I assume you mean "a username and corresponding password in the remote domain". 我假设您的意思是“远程域中的用户名和相应的密码”。

There is also the concept of a machine account, which is the hostname appended with $. 还有一个机器帐户的概念,它是在$后面附加的主机名。 But that's another topic. 但这是另一个话题。


Creating new user 创建新用户

Option 1 选项1

using (DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://192.168.1.1/CN=Users,DC=ad,DC=local", 
        name, password))
{
    using (DirectoryEntry newUser = directoryEntry.Children.Add("CN=CharlesBarker", "user"))
    {
        newUser.Properties["sAMAccountName"].Value = "CharlesBarker";
        newUser.Properties["givenName"].Value = "Charles";
        newUser.Properties["sn"].Value = "Barker";
        newUser.Properties["displayName"].Value = "CharlesBarker";
        newUser.Properties["userPrincipalName"].Value = "CharlesBarker";
        newUser.CommitChanges();
    }
}

Option 2 选项2

using (PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, "192.168.1.1", 
    "CN=Users,DC=ad,DC=local", name, password))
{
    using (UserPrincipal userPrincipal = new UserPrincipal(principalContext))
    {
        userPrincipal.Name = "CharlesBarker";
        userPrincipal.SamAccountName = "CharlesBarker";
        userPrincipal.GivenName = "Charles";
        userPrincipal.Surname = "Barker";
        userPrincipal.DisplayName = "CharlesBarker";
        userPrincipal.UserPrincipalName = "CharlesBarker";
        userPrincipal.Save();
    }
}

I leave as an exercise to you to find out which attribute goes into which User dialog entry field :-) 作为练习,我留给您找出哪个属性进入哪个“用户”对话框输入字段:-)

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM