c# - 从网络外的本地计算机确定用户 Active Directory 组

标签 c# .net authentication active-directory

我当前的项目要求我根据 Active Directory 组验证用户。问题是,计算机可能并不总是连接到域,但用户可能仍需要运行该工具。我知道我在未连接时无法查询 Active Directory,而是尝试查询机器 SAM (MSAM)。

当我与网络断开连接时,我无法确定当前用户。这是我正在使用的:

PrincipalContext principalctx = new PrincipalContext(ContextType.Machine);
UserPrincipal uprincipal = new UserPrincipal(principalctx);

从这一点来说,我如何询问当前登录到本地机器的人。

当连接到域时,我可以使用 UserPrincipal.Current 进行查询.如果我没有连接到域它会失败说 "The server could not be contacted" .注意:使用上面的代码无法使用此方法,相反我可以放弃 PrincipalContext并直接查询当前用户。确定当前用户后,我可以查询 GetGroups()并确定他们是否属于所需的组之一。

另外,有人可以描述三个ContextType选项ApplicationDirectory, Domain, Machine .恐怕我没有完全理解每个选项,因此可能会错误地使用它。

最佳答案

从一开始:

My current project requires that I validate a user against Active Directory groups. The catch is, the computer may not always be connected to the domain but users may still need to run the tool.



此时,您必须接受攻击者可以绕过任何强制安全措施,因为它完全在客户端上强制执行。不完全是解决方案的一部分,但请记住它。

I understand that I can't query Active Directory while I'm not connected, instead I'm trying to query the Machine SAM (MSAM).



Security Accounts Manager仅存储本地帐户(MACHINENAME\Administrator 等)。它不会有域用户凭据。你在想 LSA cache ,它记住最后 N 个域登录的凭据(其中 N 是组策略配置的从 0 到 50 的数字)和最后 N 个 SID 到名称映射(默认为 128, configurable via registry )。安全帐户管理器仅将域帐户存储在域 Controller 上。

I am having trouble determining the current user while I'm disconnected from the network. Here's what I'm using: PrincipalContext principalctx = new PrincipalContext(ContextType.Machine); UserPrincipal uprincipal = new UserPrincipal(principalctx);

Also, can someone please describe the three ContextType options ApplicationDirectory, Domain, Machine. I'm afraid I don't fully understand each option and therefore may be using it incorrectly.



如上所述,信息没有被缓存,但是 ContextType 枚举可以描述如下:

来自 MSDN:
  • 域:域名商店。这表示 AD DS 存储。 (正如它所说,这是针对域帐户的,如 Active Directory 的 LDAP 目录访问 - 这需要网络访问)
  • 申请目录:应用程序目录存储。这表示 AD LDS 存储。 ( AD Lightweight Directory Services(以前称为 ADAM)是较小版本的 Active Directory,旨在存储单个应用程序的凭据。它与本讨论无关,但也使用 LDAP。)
  • 机器:电脑店。这代表 SAM 存储。 (仅枚举本地帐户)

  • From this point, how do I ask who is currently logged into the local machine.



    您始终可以通过调用 WindowsIdentity.GetCurrent() 来检查登录用户。 .如果登录发生在离线状态,这将返回登录用户的 SID 和组 SID,可能已缓存。

    When connected to the domain, I can query using UserPrincipal.Current. If I am not connected to the domain it will fail saying "The server could not be contacted". Note: this method is not available using the above code, instead I can forgo the PrincipalContext and directly query the current user. With the current user identified I can query GetGroups() and determine if they're in one of the required groups.



    要确定组成员身份,请检查您想要的组 SID 是否在 WindowsIdentity.GetCurrent 返回的身份中。 .如果您没有在访问控制系统中使用 SID,您可以通过调用 SecurityIdentifier.Translate 将名称转换为 SID。 .您需要在线翻译它,然后将其缓存以供离线使用。它可以存储为字符串或二进制文件,因此两者都适合注册表。
    // while we are online, translate the Group to SID
    // Obviously, administrators would be a bad example as it is a well known SID...
    var admins = new NTAccount("Administrators");
    var adminSid = (SecurityIdentifier)admins.Translate(typeof(SecurityIdentifier));
    
    // store the sid as a byte array on disk somewhere 
    byte[] adminSIDbytes = new byte[adminSid.BinaryLength];
    adminSid.GetBinaryForm(adminSIDbytes, 0);
    
    // at time of check, retrieve the sid and check membership
    var sidToCheck = new SecurityIdentifier(adminSIDbytes, 0);
    if (!wi.Groups.Contains(sidToCheck))
        throw new UnauthorizedAccessException("User is not a member of required group");
    

    关于c# - 从网络外的本地计算机确定用户 Active Directory 组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17687133/

    相关文章:

    c# - 将字符串列表转换为字节数组

    c# - 改进 LinkLabel - 使用系统手形光标并更改链接颜色

    c# - 使用 ASP.net 和 jquery 进行拖放

    .net - 如何将 Dapper 的强类型查询参数与 Sybase ASE 结合使用?

    c# - 委托(delegate)使用 : Business Applications

    authentication - 在带有 Windows Server 2008 的 IIS 7 上使用委派设置 Kerberos 身份验证

    Android登录按钮在按下时隐藏

    c# - 使用 JSON 结果返回多个对象

    c# - IIS:使用 C# 的 IIS 的 wwwroot 目录?

    javascript - 如何使用 Office-js-helper 的身份验证获取用户信息?