You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用JNI获取Active Directory用户属性?新手入门咨询

嘿,刚好我对这块有点了解,来给你梳理清楚!

先搞懂什么是Active Directory

简单来说,Active Directory(简称AD)是微软推出的目录服务,企业里几乎都会用它来集中管理用户账号、计算机、权限组这些资源。比如你公司的办公电脑登录账号、邮件账号,大概率都是存在AD里的,管理员可以通过AD统一设置谁能访问哪些系统、文件。

用JNI获取AD用户属性的实现思路

JNI是Java调用本地C/C代码的桥梁,所以核心思路就是:Java层声明native方法,然后用C/C调用Windows原生的AD接口来查询用户属性,最后把结果返回给Java。下面是具体步骤:

1. 先熟悉Windows的AD本地API

Windows提供了两种主要的本地接口来操作AD:

  • ADSI(Active Directory Service Interfaces):基于COM的接口,封装了LDAP的复杂操作,用起来更简单
  • LDAP API:更底层的LDAP协议接口,灵活性更高

推荐先用ADSI上手,门槛低一些。

2. 编写Java层的Native方法

先写一个Java类,声明要调用的native方法,同时加载后续编译好的动态链接库:

public class ADUserReader {
    // 静态代码块加载本地库,"ADUserNative"是你编译出的dll文件名(不带.dll后缀)
    static {
        System.loadLibrary("ADUserNative");
    }

    // Native方法:传入用户名,返回AD用户的属性字符串(你也可以改成返回Map等结构)
    public native String getUserADAttributes(String username);
}

3. 生成JNI头文件

用Java的工具生成对应JNI的头文件,打开命令行,先编译Java类:

javac ADUserReader.java

然后用javah生成头文件:

javah -jni ADUserReader

执行后会得到一个ADUserReader.h的头文件,里面是JNI函数的标准声明,接下来的C/C++代码要实现这个函数。

4. 编写C/C++实现代码

这里用ADSI来实现,需要链接Windows的ADSI相关库。代码示例如下:

#include "ADUserReader.h"
#include <windows.h>
#include <adsi.h>
#include <atlbase.h>
#include <string>
#include <comutil.h>

// 链接ADSI所需的库
#pragma comment(lib, "adsiid.lib")
#pragma comment(lib, "activeds.lib")
#pragma comment(lib, "comsuppw.lib")

JNIEXPORT jstring JNICALL Java_ADUserReader_getUserADAttributes(JNIEnv *env, jobject obj, jstring jUsername) {
    // 把Java字符串转成C字符串
    const char* username = env->GetStringUTFChars(jUsername, NULL);
    if (username == NULL) {
        return NULL;
    }

    HRESULT hr;
    CComPtr<IADs> pADsUser;
    std::string resultStr;

    // 构造AD用户的LDAP路径,需要替换成你的实际AD域名和用户组织单元
    std::string ldapPath = "LDAP://CN=" + std::string(username) + ",OU=Users,DC=yourcompany,DC=com";
    
    // 绑定到AD用户对象:如果需要身份验证,可以在第2、3参数传入有权限的账号和密码
    hr = ADsOpenObject(
        ldapPath.c_str(),
        NULL,  // 用户名,NULL表示用当前登录用户身份
        NULL,  // 密码
        ADS_SECURE_AUTHENTICATION,  // 安全认证方式
        IID_IADs,
        (void**)&pADsUser
    );

    if (SUCCEEDED(hr)) {
        // 获取用户属性,这里举几个常用的例子,你可以根据需求添加更多
        VARIANT attrValue;
        VariantInit(&attrValue);

        // 获取用户全名(displayName)
        hr = pADsUser->Get(CComBSTR("displayName"), &attrValue);
        if (SUCCEEDED(hr) && attrValue.vt != VT_EMPTY) {
            resultStr += "全名: " + std::string(_bstr_t(attrValue.bstrVal)) + "\n";
            VariantClear(&attrValue);
        }

        // 获取邮箱(mail)
        hr = pADsUser->Get(CComBSTR("mail"), &attrValue);
        if (SUCCEEDED(hr) && attrValue.vt != VT_EMPTY) {
            resultStr += "邮箱: " + std::string(_bstr_t(attrValue.bstrVal)) + "\n";
            VariantClear(&attrValue);
        }

        // 获取用户登录名(userPrincipalName)
        hr = pADsUser->Get(CComBSTR("userPrincipalName"), &attrValue);
        if (SUCCEEDED(hr) && attrValue.vt != VT_EMPTY) {
            resultStr += "登录名: " + std::string(_bstr_t(attrValue.bstrVal)) + "\n";
            VariantClear(&attrValue);
        }
    } else {
        // 绑定失败,返回错误信息
        resultStr = "绑定AD用户失败: " + std::string(_com_error(hr).ErrorMessage());
    }

    // 释放Java字符串资源
    env->ReleaseStringUTFChars(jUsername, username);
    // 把C字符串转成Java字符串返回
    return env->NewStringUTF(resultStr.c_str());
}

注意:LDAP://CN=...这个路径要根据你的实际AD环境修改,比如你的用户在OU=研发部,DC=company,DC=cn下,就要调整对应的部分。

5. 编译C/C++代码为动态链接库

用Visual Studio的话,创建一个Win32动态链接库项目,把上面的代码添加进去,确保项目设置里链接了需要的库(adsiid.lib、activeds.lib、comsuppw.lib),编译后会生成ADUserNative.dll。

6. 运行Java测试程序

把生成的dll放在Java程序能找到的位置(比如和class文件同目录,或者加入系统PATH),然后写个测试类:

public class ADTest {
    public static void main(String[] args) {
        ADUserReader reader = new ADUserReader();
        // 替换成你AD里存在的用户名
        String userAttrs = reader.getUserADAttributes("zhangsan");
        System.out.println(userAttrs);
    }
}

运行这个类,就能看到AD用户的属性啦!

一些关键注意事项
  • 环境要求:运行程序的机器必须能访问AD服务器,最好是加入了AD域的机器
  • 权限问题:如果当前登录用户没有访问AD的权限,要在ADsOpenObject里传入有查询权限的AD账号和密码
  • 错误处理:JNI代码里要做好异常捕获,避免Java程序崩溃
  • 替代方案:其实Java本身有JNDI(Java Naming and Directory Interface)可以直接操作AD,不需要JNI,如果你不是必须用JNI的话,用JNDI会更简单哦!

内容的提问来源于stack exchange,提问作者Kasinaat 007

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:34:34