【问题标题】:How to check if user belongs to certain AD group in java如何检查用户是否属于java中的某个AD组
【发布时间】:2012-06-12 23:29:46
【问题描述】:

我知道这一定是一个非常简单的问题,但我是 java 新手,很难获得我需要的确切代码。我需要做的是从 Windows 获取当前登录的用户名,并检查该用户是否属于需要在某个配置文件中定义的特定 AD 用户组。在 C# 中很容易做到,但我不知道如何在 JAVA 中做到这一点。示例代码会很棒。在 c# 中,我会将安全组放入 App.Config 到应用程序设置中,然后我可以获取当前登录用户的 Windows 身份,然后遍历用户所属的所有组并与所需的匹配。我需要在 java 中做同样的事情

【问题讨论】:

  • “我发现很难得到我需要的准确代码。”不幸的是,这根本不是巧合:Java 与 Windows 开发平台的集成与 C# 的集成水平不匹配。上一次我需要做类似的事情时,我不得不跳过 Open LDAP 的各种麻烦(包括调试 Novell 代码中的并发问题)。

标签: java windows active-directory


【解决方案1】:

如果您只关心当前登录的 Windows 用户(即您的 Java 程序将在 Windows 上运行)并且不介意使用 JNA,您可以使用 platform.jar、Advapi32Util#getCurrentUserGroups() 中提供的函数获取用户所属的组。

例如:

import com.sun.jna.platform.win32.Advapi32Util;

for (Advapi32Util.Account account : Advapi32Util.getCurrentUserGroups()) {
    System.out.println(account.fqn);
}

这还利用了当用户登录时,Windows 会缓存所有组(包括包含该用户所属的其他组的组)中的用户成员身份这一事实。


这里的要求似乎有点不具体,并且开始转向可能不太适合 SO 的领域,但无论如何我都会试一试。

最终,系统的运行位置决定了设置的难度。如果您要在基于 Windows 的服务器上运行,该服务器连接到您正在验证的同一个域,那么您应该查看Waffle,它提供了一个 servlet、一个 Spring Security 过滤器、一个 JAAS 插件和其他一些方式您可以实施 Windows 集成身份验证,该身份验证使用本机 Windows 方法来加载 Windows 身份和关联的 Active Directory 组。这将为您提供最类似于将 IIS 和 WIA 与 .NET 框架应用程序一起使用的体验。这样做的缺点是服务器需要在 Windows 系统上运行。

不幸的是,在非 Windows 环境中运行将需要更多设置和配置。集成度最高的解决方案可能是 Spring Security,它的 a Kerberos extension 能够提供 SPNEGO(Windows 集成身份验证)。上面的链接包含有关启动和运行 Kerberos 过滤器所需的详细信息(我相信它们仍然是最新的)。要访问组信息,您需要更改示例 security.xml 文件中的 userDetailsService 值。这里最简单的做法是提供一个适当配置的LdapUserDetailsService 作为这里的对象。我对 Spring 的经验并不多,但看起来配置会像这样(这缺少 contextSource)。

<bean id="adUserSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
    <constructor-arg value="dc=domain,dc=com"/>
    <constructor-arg value="(sAMAccountName={0})"/>
    <constructor-arg ref="contextSource" />
</bean>

<bean id="adAuthoritiesPopulator" class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
    <constructor-arg ref="contextSource"/>
    <constructor-arg value="dc=domain,dc=com" />
    <property name="groupSearchFilter" value="(member={0})"/>
    <property name="rolePrefix" value="ROLE_"/>
    <property name="searchSubtree" value="true"/>
    <property name="convertToUpperCase" value="true"/>
</bean>

<bean id="userDetailsService" class="org.springframework.security.ldap.userdetails.LdapUserDetailsService">
    <constructor-arg ref="adUserSearch"/>
    <constructor-arg ref="adAuthoritiesPopulator"/>
</bean>

这应该会为您提供一个经过 Kerberos 身份验证的用户及其关联的组。

如果 Spring Security 不可接受,您可以尝试使用 Shiro 和 the pure-Java SPNEGO filter 滚动您自己的版本,但展示一个示例需要基本上编写一个程序。

我希望这会有所帮助。一旦您决定了一种方法,可能适合将更具体的问题作为 SO 类型的问题来解决。

【讨论】:

  • 非常感谢。我会试试看。这个 com.sun.jna.platform.win32.Advapi32Util 包,它是已经包含在 Java 标准安装中还是我必须以某种方式安装它。我是java新手所以不知道。
  • 另外,它在非 Windows 机器上的表现如何?
  • @fenix2222:它不包含在标准 Java 包中。它是 JNA 的一部分(我在上面链接过)。这在非 Windows 机器上根本不起作用,因为它使用 Win32 API 来实际进行查找(因此我在答案开始时需要注意)。如果您能更清楚地了解您的要求,我很乐意为您提供帮助。
  • 如果你需要在非 Windows 环境下工作的东西,你可以试试the code in this blog post(通过this answer的评论找到)
  • 好的,我们的应用程序允许不同类型的身份验证:用户名/密码、OpenAuth 和 Active Directory。因此,如果在配置文件中应用程序配置为具有 AD 身份验证并指定了安全组,那么我希望能够自动检查登录用户(无需输入密码)并检查他是否属于指定的组。我正在使用 Apache Directory Studio 为我构建 AD 以进行测试。我知道我应该能够使用 Spring LDAP,但是网络上的所有示例都显示用户必须提供密码的身份验证,我不希望那样。请帮忙
【解决方案2】:

你可以像这样得到所有没有 JNA 的组:

String groups[] = (new com.sun.security.auth.module.NTSystem()).getGroupIDs();

显然这仅适用于 Windows,甚至在 Windows 上也不鼓励使用 com.sun.* 包。结果说明见this。

【讨论】:

    【解决方案3】:

    这可以通过 Java SE API 完成,而无需直接使用 com.sun.* 包。使用 Java Authentication and Authorization Service (JAAS)(javax.security.auth.* 和 javax.security.auth.login.*)访问此信息。使用以下条目创建 JAAS config file:

    sampleApp {
        com.sun.security.auth.module.NTLoginModule required debug=false;
    };
    

    将该条目保存为sampleapp_jaas.config。接下来设置系统属性,以便 Java 将查找配置文件。

    -Djava.security.auth.login.config==sampleapp_jaas.config
    

    请注意,双等号具有特殊含义。有关加载顺序的详细信息,请参阅com.sun.security.auth.login.ConfigFile。

    然后创建将在 JAAS 配置中查找条目的 LoginContext。调用 login 填充主题,然后访问代表用户组的主体。

    LoginContext l = new LoginContext("sampleApp");
    l.login();
    try {
        Subject s = l.getSubject();
        for (Principal p : s.getPrincipals()) {
            System.out.println(p);
        }
    } finally {
        l.logout();
    }
    

    使用此设置,Java 将使用 com.sun.security.auth.module.NTSystem 类来获取信息,但您的任何代码都不会被硬连线到非标准 API。

    【讨论】:

      猜你喜欢
      • 2012-08-15
      • 1970-01-01
      • 1970-01-01
      • 2016-04-06
      • 1970-01-01
      • 2014-04-08
      • 2018-06-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多