问题描述:
通过Apache Ldap Api操作Active Directory添加用户,代码如下:

DefaultEntry entry = new DefaultEntry(
        getDn(),    // The Dn
        "objectClass: top",
        "objectClass: person",
        "objectClass: organizationalPerson",
        "objectClass: user",
        "sAMAccountName", this.loginName,
        "userPrincipalName", getFullLoginName(),
        "givenName", this.givenName,
        "cn", getFullName(),
        "sn", this.familyName
);

运行测试的时候没问题(主要那个时候确实没想过用中文测试),好了,到正式使用的时候,因为用户姓名是中文,代码挂了。如下:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 20167
    at org.apache.directory.api.util.Strings.toLowerCase(Strings.java:1896)
    at org.apache.directory.api.ldap.model.ldif.LdifAttributesReader.parseEntry(LdifAttributesReader.java:335)

我首先怀疑这是个bug嘛,于是先去Apache Ldap Api的Issue列表查了一下,嘿,果然有,但是。。。已经被关闭,还打了个不会修改的标记,为啥咧?
理由也很简单,上述格式是LDIF格式,只能使用ASCII编码,额。。。中文显然不在内啊。不过该Issue也提到了,对于含有unicode字符的数据进行Base64编码即可。哟西,明白了,开干!

DefaultEntry entry = new DefaultEntry(
        Base64.encodeToString(getDn().getBytes(), false),    // The Dn
        "objectClass: top",
        "objectClass: person",
        "objectClass: organizationalPerson",
        "objectClass: user",
        "sAMAccountName", this.loginName,
        "userPrincipalName", getFullLoginName(),
        "givenName", Base64.encodeToString(this.givenName.getBytes(), false),
        "cn", Base64.encodeToString(getFullName().getBytes(), false),
        "sn", Base64.encodeToString(this.familyName.getBytes(), false)
);

这样子应该就可以喽?
现实总是残酷的。没有报错,对!没有报错!但是操作没有成功!尼玛这是什么样的一种精神!
没办法,只能打开log仔细看,嗯,还是找到蛛丝马迹了。

Message ID : 4
    Add Response
        Ldap Result
            Result code : (NO_SUCH_OBJECT) noSuchObject
            Matched Dn : ''
            Diagnostic message : '0000208D: NameErr: DSID-031001EE, problem 2001 (NO_OBJECT), data 0, best match of:
    ''

为啥咧?为啥咧?为啥咧?抓狂了。。。。嗯,花了整整一天,毫无进展,资料也少,也没地方问,这东西毕竟小众啊,悲催。
好吧,还是回去看文档吧,看看有没有其他途径。
嗯,果然找到了。既然LDIF格式这么麻烦,绕开它,直接创建。

DefaultEntry entry = new DefaultEntry();
entry.setDn(getDn());
entry.add( "objectClass", "top", "person", "organizationalPerson" , "user"  );
entry.add( "sAMAccountName", this.loginName );
entry.add( "userPrincipalName",  getFullLoginName() );
entry.add( "givenName", this.givenName.getBytes()  );
entry.add( "cn", getFullName()  );
entry.add( "sn", this.familyName  );

经测试,没有报错,成功创建了。
嗯,其实就是这么简单。