本文介绍了在 C# 中验证远程 Active Directory 的用户的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试从我的机​​器验证属于远程 ActiveDirectory 的用户,这与当前机器或用户域不同.我的机器和远程 ActiveDirectory 机器之间将不存在信任.

初步尝试

我尝试对用户进行身份验证(输入:sAMAccountName、机器的 ipaddress、机器的域用户名(管理员")和机器的密码(***).能够得到具有 'sAMAccountName' 的用户确实存在于 ActiveDirectory 中的结果.

我的要求:

  1. 假设已经在 ActiveDirectory 中创建了一个用户(qwerty")

  2. 从我的本地机器,我将获得以下信息,

    一个.远程 ActiveDirectory ipaddress

    B.远程 ActiveDirectory 计算机的用户名和密码.

    c.用户qwerty"的用户名和密码

  3. 我需要检查远程 ActiveDirectory 的用户列表中是否存在用户qwerty",并验证输入的 密码 在 ActiveDirectory 的用户列表中是否相同

我尝试过的代码:

 DirectoryEntry entry = new DirectoryEntry("LDAP://ipaddress/DC=dinesh,DC=com", name, password);DirectorySearcher searcher = new DirectorySearcher(entry);searcher.Filter = "(sAMAccountName=" + 姓名 + ")";尝试{SearchResult adsSearchResult = adsSearcher.FindOne();isValid = true;adsEntry.Close();}捕获(异常前){adsEntry.Close();}

在验证远程 ActiveDirectory 中的用户之前,我是否需要在本地计算机和远程 ActiveDirectory 计算机之间建立信任?如果是,请告诉如何做到;

创建信任后,如何验证用户?

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

我可以使用 Rainer 建议的解决方案,但遇到了一个新问题.当我通过不同机器上的 C# 代码创建新用户时,某些属性设置不正确.

是否需要在创建用户时强制设置?

解决方案

首先是一些基础知识(独立于这个问题)

身份验证

系统会检查 Bob 是否真的是 Bob.在 Active Directory 环境中,这通常是通过从工作站登录域来完成的,Bob 输入他的用户名和密码,然后他获得 Kerberos 票证.稍后,如果他想访问例如远程文件服务器上的文件共享,他不再需要登录,无需输入用户名/密码即可访问文件.

授权

系统检查允许 Bob 访问哪些资源.通常Bob在域组中,一个组在资源的ACL(访问控制列表)中.

如果有多个信任域,Bob 需要在一个域中登录,并且可以访问所有其他域中的资源.这是使用 Active Directory 的主要原因之一:单点登录

检查用户/密码是否有效

如果您有用户名和密码并想检查密码是否有效,则必须登录域.没有办法仅仅检查密码是否正确".登录是指:如果有安全策略如果超过 3 次无效登录,则锁定帐户",即使您只想检查用户+密码",检查错误密码也会锁定帐户.

使用 .NET 目录服务功能

我在这里假设该进程要么由人类帐户作为普通程序运行,要么该程序是 Windows 服务或在域技术用户"帐户下运行的计划任务.在这种情况下,您无需提供使用 AD 功能的凭据.如果访问其他信任的 AD 域,也是如此.如果您想登录到外域",并且没有信任,则需要提供用户名+密码(如您的代码中所示).

手动"验证用户

通常不需要这样做.示例:ASP.NET Intranet 使用情况.用户访问当前域或信任域上的 Web 应用程序,身份验证由浏览器和 IIS在后台"完成(如果集成的 Windows 身份验证打开).所以你永远不需要在应用程序中处理用户密码.

我没有看到很多使用代码处理密码的用例.

有人可能认为您的程序是用于存储紧急用户帐户/密码的辅助工具.并且您想定期检查这些帐户是否有效.

这是一个简单的检查方法:

使用 System.DirectoryServices.AccountManagement;...主体上下文主体上下文 =新的 PrincipalContext(ContextType.Domain, "192.168.1.1");bool userValid = principalContext.ValidateCredentials(name, password);

还可以使用较旧的原始 ADSI 函数:

使用 System.DirectoryServices;....bool userOk = false;string realName = string.Empty;使用 (DirectoryEntry directoryEntry =new DirectoryEntry"LDAP://192.168.1.1/DC=ad,DC=local", name, password)){使用 (DirectorySearcher searcher = new DirectorySearcher(directoryEntry)){searcher.Filter = "(samaccountname=" + name + ")";searcher.PropertiesToLoad.Add("displayname");SearchResult adsSearchResult = searcher.FindOne();如果(adsSearchResult != null){if (adsSearchResult.Properties["displayname"].Count == 1){realName = (string)adsSearchResult.Properties["displayname"][0];}用户确定 = 真;}}}

如果您的真正要求实际上是用户+密码的有效性检查,您可以通过以下方式之一进行.

但是,如果是普通应用程序",只想检查输入的凭据是否有效,则应该重新考虑您的逻辑.在这种情况下,您最好依靠 AD 的单点登录功能.

如果还有什么问题,欢迎留言.

B.远程 ActiveDirectory 计算机的用户名和密码.

这听起来有点不清楚.我假设您的意思是远程域中的用户名和相应的密码".

还有机器账号的概念,就是主机名后加$.但那是另一个话题了.

创建新用户

选项 1

using (DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://192.168.1.1/CN=Users,DC=ad,DC=local",姓名、密码)){使用 (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();}}

选项 2

using (PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, "192.168.1.1","CN=Users,DC=ad,DC=local", 姓名, 密码)){使用 (UserPrincipal userPrincipal = new UserPrincipal(principalContext)){userPrincipal.Name = "CharlesBarker";userPrincipal.SamAccountName = "CharlesBarker";userPrincipal.GivenName = "查尔斯";userPrincipal.Surname = "巴克";userPrincipal.DisplayName = "CharlesBarker";userPrincipal.UserPrincipalName = "CharlesBarker";userPrincipal.Save();}}

我留给你一个练习,找出哪个属性进入哪个用户对话框输入字段:-)

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. There will be no trust between my machine and remote ActiveDirectory machine.

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.

My Requirement:

  1. Imagine that already a user("qwerty") is created in ActiveDirectory

  2. From my local machine, I will have the following information,

    a. Remote ActiveDirectory ipaddress

    b. Remote ActiveDirectory machine's username and password.

    c. Username and password of User "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

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? 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. When I create a new user via C# code from a different machine, then some properties do not set properly.

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. Later, if he wants to access e.g. 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. Usually Bob is in domain groups, and a group is in the ACL (access control list) of the resource.

If there are multiple trusting domains, Bob needs to login in one domain, and can access resources in all other domains.This is one of the main reasons using Active Directory: single sign on

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".

Using .NET Directory Service functions

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. In this case, you do not need to provide credentials for using the AD functions. If accessing other trusting AD domains, this is also true.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. 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). 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:

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.

If there are further questions, please comment.

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

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

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 :-)

这篇关于在 C# 中验证远程 Active Directory 的用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-20 20:06