Java Active Directory LDAP问题让我抓狂

Java Active Directory LDAP问题让我抓狂,java,active-directory,ldap-query,Java,Active Directory,Ldap Query,我已经编写了一个Java应用程序来检索所选的AD用户帐户属性,以尝试将公司的HR员工记录与AD进行匹配。除了属性“accountExpires”在我的代码中总是返回null之外,其他一切都可以完美地工作。当我使用ApacheLDAP查看器(Eclipse插件)检查相同用户帐户的示例时,我可以看到日期/时间和长值 下面是我的代码,它适用于除检索“accountExpires”属性之外的所有内容。 package com.痤疮.LDAPRealmTest import java.io.Buffere

我已经编写了一个Java应用程序来检索所选的AD用户帐户属性,以尝试将公司的HR员工记录与AD进行匹配。除了属性“accountExpires”在我的代码中总是返回null之外,其他一切都可以完美地工作。当我使用ApacheLDAP查看器(Eclipse插件)检查相同用户帐户的示例时,我可以看到日期/时间和长值

下面是我的代码,它适用于除检索“accountExpires”属性之外的所有内容。 package com.痤疮.LDAPRealmTest

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.Hashtable;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import javax.naming.NameClassPair;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.Attributes;
import javax.naming.directory.Attribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;

public class LDAPCtxTest {
    DirContext ctx = null;
    StringBuffer sb = new StringBuffer();
    int counter=0;
    SearchControls controls;
    private final static long DIFF_NET_JAVA_FOR_DATE_AND_TIMES = 11644473600000L;

    public LDAPCtxTest() {
        try {
            System.out.println("Active Directory search test"); 
            Hashtable<String, String> env = new Hashtable<String, String>();

        /*  Begin by defining the environment properties and getting the InitialDirContext class object initialized.
          */ 

        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, "connection_string"); 
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.SECURITY_PRINCIPAL, "CN=LDAP_USER,OU=Service Accounts,OU=System Administration,DC=acne,DC=com,DC=au");
        env.put(Context.SECURITY_CREDENTIALS, "test01");
        env.put(Context.REFERRAL, "follow");

        ctx = new InitialDirContext(env);
          // Create the search controls          
          controls = new SearchControls(); 

          //Specify the attributes to return 
          String returnedAtts[]={"sn","name", "accountExpires", "sAMAccountName", "department","telephoneNumber","userAccountControl","cn","pwdLastSet","accountExpires","objectcategory"}; 
          controls.setReturningAttributes(returnedAtts); 

          //Specify the search scope 
          controls.setSearchScope(SearchControls.SUBTREE_SCOPE); 

          //String searchFilter = "(&(objectClass=user)(userAccountControl=512))";
          String searchFilter = "(&(objectCategory=person)(objectClass=user)(userAccountControl=512))";
          //Specify the Base for the search 
          String searchBase = "DC=acne,DC=com,DC=xx"; //this doesn't seem to work so replaced with empty string which is ok
          //initialize counter to total the results 
          //controls.setCountLimit(100); // limits the search result to 200

          File outFile = new File("C:\\temp\\", "ldaptest.txt");
          BufferedWriter bw = new BufferedWriter(new FileWriter(outFile));
          bw.write("Counter,sAMAccountName,userAccountControl,name,AccountExpiry\n");
          NamingEnumeration<SearchResult> answer = ctx.search("", searchFilter, controls); 
          //Loop through the search results
            while (answer.hasMoreElements()) 
            {
                SearchResult sr = (SearchResult)answer.next();
                Attributes attrs = sr.getAttributes();
                Attribute attrAccountControl = attrs.get("userAccountControl");
                Attribute attrName = attrs.get("name");
                Attribute attrAccountExpire = attrs.get("accountExpires");
                Attribute attrSAMAccount = attrs.get("sAMAccountName");

                counter++;
                sb.append(counter+","+attrSAMAccount.get(0)+","+attrAccountControl.get(0)+","+attrName.get(0)+ ","+attrAccountExpire+"\n");
                System.out.println(counter + " " + attrSAMAccount.get(0) + "..." + attrAccountControl.get(0));
            } 
          bw.write(sb.toString());
          bw.close();
          System.out.println("The End");
          ctx.close();
          System.out.println("LDAP connected ok");
    } catch (NamingException ne) {
        System.out.println("LDAP connect FAILED");

    } catch (Exception e) {
        e.printStackTrace(); 
    }       
}

private Date getDateTimeFrom(String adDateTimeStr) {
    long adDateTime = Long.parseLong(adDateTimeStr);
    long milliseconds = (adDateTime / 10000) - DIFF_NET_JAVA_FOR_DATE_AND_TIMES;
    //long milliseconds = (adDateTime / 10000) - DIFF_NET_JAVA_FOR_DATE_AND_TIMES;
    Date dateVal = new Date(milliseconds);
    return dateVal;
} 


public static void main(String[] args) {
    new LDAPCtxTest();
}
导入java.io.BufferedWriter;
导入java.io.File;
导入java.io.FileWriter;
导入java.util.Hashtable;
导入java.util.Calendar;
导入java.util.Date;
导入java.util.concurrent.TimeUnit;
导入javax.naming.NameClassPair;
导入javax.naming.Context;
导入javax.naming.NamingEnumeration;
导入javax.naming.NamingException;
导入javax.naming.directory.BasicAttribute;
导入javax.naming.directory.BasicAttribute;
导入javax.naming.directory.Attributes;
导入javax.naming.directory.Attribute;
导入javax.naming.directory.DirContext;
导入javax.naming.directory.InitialDirContext;
导入javax.naming.directory.SearchControls;
导入javax.naming.directory.SearchResult;
导入javax.naming.ldap.InitialLdapContext;
导入javax.naming.ldap.LdapContext;
公共类LDAPCtxTest{
DirContext ctx=null;
StringBuffer sb=新的StringBuffer();
int计数器=0;
搜索控制;
日期和时间的专用最终静态长差异网络JAVA=1164443600000L;
公共LDAPCtxTest(){
试一试{
System.out.println(“Active Directory搜索测试”);
Hashtable env=新的Hashtable();
/*首先定义环境属性并初始化InitialDirContext类对象。
*/ 
put(Context.INITIAL\u Context\u工厂,“com.sun.jndi.ldap.LdapCtxFactory”);
环境put(Context.PROVIDER_URL,“连接字符串”);
环境put(Context.SECURITY_认证,“simple”);
env.put(Context.SECURITY_PRINCIPAL,“CN=LDAP_用户,OU=servicecomports,OU=systemadministration,DC=痤疮,DC=com,DC=au”);
环境投入(Context.SECURITY_凭证,“test01”);
环境投入(Context.reference,“follow”);
ctx=新的初始目录上下文(env);
//创建搜索控件
控件=新的SearchControls();
//指定要返回的属性
字符串returnedAtts[]={“sn”、“name”、“accountExpires”、“sAMAccountName”、“department”、“telephoneNumber”、“userAccountControl”、“cn”、“pwdLastSet”、“accountExpires”、“objectcategory”};
控件。设置ReturningAttribute(ReturnedAttribute);
//指定搜索范围
控件.setSearchScope(SearchControls.SUBTREE_范围);
//字符串searchFilter=“(&(objectClass=user)(userAccountControl=512))”;
字符串searchFilter=“(&(objectCategory=person)(objectClass=user)(userAccountControl=512))”;
//指定搜索的基数
String searchBase=“DC=痤疮,DC=com,DC=xx”;//这似乎不起作用,所以替换为空字符串就可以了
//初始化计数器以合计结果
//controls.setCountLimit(100);//将搜索结果限制为200
File outFile=新文件(“C:\\temp\\”,“ldaptest.txt”);
BufferedWriter bw=新的BufferedWriter(新文件编写器(outFile));
write(“Counter,sAMAccountName,userAccountControl,name,AccountExpiry\n”);
NamingEnumeration answer=ctx.search(“”,searchFilter,controls);
//循环搜索结果
while(answer.hasMoreElements())
{
SearchResult sr=(SearchResult)answer.next();
Attributes attrs=sr.getAttributes();
属性attrAccountControl=attrs.get(“userAccountControl”);
属性attrName=attrs.get(“name”);
属性attrAccountExpire=attrs.get(“accountExpires”);
属性attrSAMAccount=attrs.get(“sAMAccountName”);
计数器++;
sb.append(计数器+”,“+attrSAMAccount.get(0)+”,“+attrAccountControl.get(0)+”,“+attrName.get(0)+”,“+attrAccountExpire+”\n”);
System.out.println(计数器+“”+attrSAMAccount.get(0)+“…”+attrsamAccountControl.get(0));
} 
写(sb.toString());
bw.close();
System.out.println(“结束”);
ctx.close();
System.out.println(“LDAP连接正常”);
}捕获(纳明异常){
System.out.println(“LDAP连接失败”);
}捕获(例外e){
e、 printStackTrace();
}       
}
私有日期getDateTimeFrom(字符串adDateTimeStr){
long adDateTime=long.parseLong(adDateTimeStr);
长毫秒=(adDateTime/10000)-日期和时间的差异;
//长毫秒=(adDateTime/10000)-日期和时间的差异;
Date dateVal=新日期(毫秒);
返回日期;
} 
公共静态void main(字符串[]args){
新的LDAPCtxTest();
}
}

我查看了与LDAP查询相关的各种线程,特别是与accountExpires相关的线程,并查看了列出LDAP属性的Microsoft站点。我在上面指定的属性名似乎没有什么问题,我也没有找到其他有类似问题的人。我不确定还有什么问题。

回答:在我从LDAP切换到LDAP后,可以访问属性“accountExpires”。理想情况下,出于安全原因,我更喜欢通过LDAP进行连接,但Active Directory管理不是我的职责范围,我会让AD专家做出决定

另请注意,我可以访问此(操作)属性,而无需将其附加到returnedAttrs“+”

,因为“accountExpires”是一个可操作的Active Directory属性,所以我尝试了以下操作,但没有成功:String retu