Java对接AD/LDAP的常见错误,以及解决办法

1、[LDAP: error code 34 - 00000057: LdapErr: DSID-0C090B60, comment: Error processing name, data 0, v1db1

在编辑AD域控帐号属性或密码的时候,经常会遇到这个错误;

为什么会产生这个错误?

我经过验证列举了几个错误的例子:

ldapContext.modifyAttributes(userDN, mods);//这是修改AD帐号密码的方法;

1)参数userDN如果不是这种格式(CN=张三,OU=测试,OU=**公司,DC=test,DC=com)就会报上面的错误;

2)参数userDN如果包含一些特殊符号,就会报上面的错误;

比如:userDN = CN=张三,OU=测试+研发,OU=**公司,DC=test,DC=com

userDN = CN=张三,OU=测试,研发,OU=**公司,DC=test,DC=com

userDN = CN=张三,OU=测试=研发,OU=**公司,DC=test,DC=com

上面的格式都会造成上面的错误,一定要把值进行转义才可以成功:

userDN = CN=张三,OU=测试\+研发,OU=**公司,DC=test,DC=com

userDN = CN=张三,OU=测试\,研发,OU=**公司,DC=test,DC=com

userDN = CN=张三,OU=测试\=研发,OU=**公司,DC=test,DC=com

体现代码就是:

userDN = userDN.replaceAll("\\+", "\\\\+");

userDN = userDN.replace("测试,研发", "测试\\,研发");

userDN = userDN.replace("测试,研发", "测试\\=研发");

2、[LDAP: error code 49 - 80090308: LdapErr: DSID-0C0903A9, comment: AcceptSecurityContext error, data 52e, v1db1

这个错误很常见,如果你在开发过程中遇到这个错误,说明:AD认证的帐号或密码不正确;

顺便多说一些使用场景:

AD认证,帐号的格式有很多种:

如果帐号属性:

sAMAccountName = zhangsan

distinguishedName = CN=张三,OU=测试\+研发,OU=**公司,DC=test,DC=com

那么帐号认证的方式可以是:

adminUID的形式会有三种,这三种可能跟AD域控的系统版本有关系,windows2008这三种方式都是兼容的,其他的未经过测试,需要验证;

property.put(DirContext.INITIAL_CONTEXT_FACTORY, LDAPEnv_Factory);
// 拥有Domain Admins角色的用户,域管理员
// adminUID的值可以为:adminUID = CN=张三,OU=测试\+研发,OU=**公司,DC=test,DC=com
// adminUID的值可以为:adminUID = zhangsan@test.com
// adminUID的值可以为:adminUID = test\zhangsan
property.put(Context.SECURITY_PRINCIPAL, adminUID);
property.put(Context.SECURITY_CREDENTIALS, adminPass);
property.put(Context.SECURITY_AUTHENTICATION, "simple");

【注意】如果AD帐号勾选了“用户下次登录时须更改密码”,也会报错。

 

3、[LDAP: error code 53 - 0000001F: SvcErr: DSID-031A120C, problem 5003 (WILL_NOT_PERFORM), data 0

这个错误也很常见,出现这个错误,一般情况是编辑AD域控的帐号属性或密码失败了。

而失败的原因有以下可能:

1)通过ldapContext.modifyAttributes(userDN, mods);修改帐号密码,需要AD开通SSL协议才行(即:通过636端口进行执行),报上面的错误,是因为使用的389端口进行执行的;

体现到代码:

property.put("java.naming.authoritative", "true");
property.put("java.naming.security.protocol", "ssl");
// 如果大家需要SkipSSLSocketFactory.java,可以联系Q Q:2753538510
property.put("java.naming.ldap.factory.socket","com.***.jndi.directory.SkipSSLSocketFactory");
property.put("java.naming.provider.url", "ldaps://x.x.x.x:636");
property.setProperty("java.naming.referral", "ignore");

作为研发人员,在建立socket连接或http/https连接的时候,习惯性增加超时时间,而AD/LDAP的连接也会习惯性增加这段:

property.put("com.sun.jndi.ldap.connect.timeout", "5000");

那么增加这一行代码, 就会造成AD的SSL连接错误:

javax.naming.CommunicationException: x.x.x.x:636 [Root exception is java.net.SocketException: Unconnected sockets not implemented]

去掉上面一行,就可以了。

2)说一下如何开通AD侧的SSL协议:

windows2012 参考该链接:教程活动目录 - 通过 SSL 启用 LDAP [ 一步一步] (techexpert.tips)

windows2008的步骤如下:

1、打开:管理工具》服务器管理器 

2、添加角色,勾选Active Directory 证书服务

图中我已经安装过了,因此会看到是灰色的; 注意:安装步骤跟windows 2012的稍微有一点差别;

3、安装完SSL,需要重启计算机,重启后,再次打开:管理工具》服务器管理器

可以看到目录里已经有证书服务了:

 使用内置程序测试验证636端口是否正常:

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要通过Java使用LDAP获取AD域用户和组织信息,需要使用Java的JNDI API。 以下是一个简单的Java程序,演示如何使用JNDI API连接到AD域并获取用户和组织信息: ``` import java.util.*; import javax.naming.*; import javax.naming.directory.*; public class ADInfo { public static void main(String[] args) { String ldapURL = "ldap://AD域服务器地址:389"; String ldapUser = "CN=LDAP查询用户,OU=xxx,DC=xxx,DC=xxx"; String ldapPassword = "LDAP查询用户密码"; String searchBase = "OU=xxx,DC=xxx,DC=xxx"; Hashtable<String, String> env = new Hashtable<String, String>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, ldapURL); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, ldapUser); env.put(Context.SECURITY_CREDENTIALS, ldapPassword); try { DirContext ctx = new InitialDirContext(env); SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); String filter = "(objectCategory=user)"; NamingEnumeration<SearchResult> results = ctx.search(searchBase, filter, searchControls); while (results.hasMore()) { SearchResult searchResult = results.next(); Attributes attributes = searchResult.getAttributes(); Attribute attribute = attributes.get("cn"); String cn = (String) attribute.get(); System.out.println(cn); } filter = "(objectCategory=organizationalUnit)"; results = ctx.search(searchBase, filter, searchControls); while (results.hasMore()) { SearchResult searchResult = results.next(); Attributes attributes = searchResult.getAttributes(); Attribute attribute = attributes.get("ou"); String ou = (String) attribute.get(); System.out.println(ou); } ctx.close(); } catch (NamingException e) { e.printStackTrace(); } } } ``` 在上面的代码中,替换以下变量: - ldapURL:AD域服务器地址和端口号 - ldapUser:用于查询AD域的LDAP用户的DN - ldapPassword:用于查询AD域的LDAP用户的密码 - searchBase:要搜索的AD域的基本DN 该程序连接到AD域并搜索用户和组织。它使用过滤器来限制搜索结果,只搜索用户和组织单位对象。它还使用SearchControls对象来设置搜索范围。 对于每个搜索结果,程序从属性中提取cn或ou,并将其打印到控制台上。 请注意,此代码需要在Java应用程序中包含JNDI API类路径。如果您使用Maven或Gradle之类的构建工具,则可以将以下依赖项添加到项目中: ``` <dependency> <groupId>com.sun.jndi</groupId> <artifactId>ldap</artifactId> <version>1.2.1</version> </dependency> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值