由于公司需要做一个基于Ldap的用户认证中心服务,需要将mysql中的用户数据导入到LDAP中,然后基于Ldap做用户的认证。之前完全没有接触过LDAP,所以本文记录学习中碰到的问题。
1.LDAP入门
参考资料:
- http://blog.didispace.com/spring-boot-ldap-user/
- https://www.cnblogs.com/obpm/archive/2010/08/28/1811065.html
2.windows server2012 搭建Active Directory
参考资料:
- [Windows Server 2012 R2 创建AD域] https://www.cnblogs.com/wanggege/p/4605678.html
- [windwows Server 2012 R2 创建AD域证书] https://blog.csdn.net/hc1017/article/details/81293323
2.1 为什么要搭建AD CA?
因为Ldap是区分两种方式ldap:192.168.1.167:389
和 ldaps:192.168.1.167:636
389端口新建用户是无密码禁用的,636端口能在创建有密码启用的用户
当需要对用户进行修改密码,启用禁用都需要使用636端口,这就需要搭建AD CA并且将证书导入到本地JDK中。
2.2 搭建CA证书注意
要确定勾选企业
,选择个人
可能导致636端口不能使用,使用telnet测试端口是否通
3.SpringBoot集成ldap
参考资料:
- [SpringBoot集成ldap] https://www.jianshu.com/p/65b06e74bc41
- [Spring-ldap官方文档] https://docs.spring.io/spring-ldap/docs/2.1.0.RELEASE/reference/
4.遇到的问题汇总
4.1
从window server上下载了证书,然后将证书导入到jdk中,还是报下面的错误。这是由于jdk版本问题导致的,我使用jdk1.8.191导致这个问题,最后换成jdk1.8.161(这个问题搞了好久,没想到jdk版本会有问题)
参考链接:https://stackoverflow.com/questions/51449801/how-to-disable-endpoint-identification-for-java-1-8-181-version
javax.naming.CommunicationException: simple bind failed: 192.168.1.167:636 [Root exception is javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names matching IP address 192.168.1.167 found]
at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:219)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2791)
at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:319)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:192)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:210)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:153)
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:83)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.init(InitialContext.java:244)
at javax.naming.ldap.InitialLdapContext.<init>(InitialLdapContext.java:154)
at com.yungu.ldap.SSLTest.ldapConnect(SSLTest.java:31)
at com.yungu.ldap.SSLTest.main(SSLTest.java:41)
4.2
修改密码
javax.naming.directory.AttributeInUseException: [LDAP: error code 20 - mail attribute has duplicate value.];
修改用户密码应该使用这种方法修改
/**
* 修改密码
*
* @param dn
* @param newPassword
*/
public void updatePassword(Name dn, String newPassword) {
ModificationItem[] modificationItems = new ModificationItem[1];
Attribute attr = new BasicAttribute("unicodePwd", buildEncodePwd(newPassword));
modificationItems[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr);
ldapTemplate.modifyAttributes(dn, modificationItems);
}
4.3
用户密码是unicodePwd
属性,且密码必须满足以下三点
/**
* 将密码进行UTF-16LE编码
*/
private byte[] buildEncodePwd(String pwd) {
//LDAP用户密码必须要用""给括起来,必须使用UTF-16LE编码,必须使用LDAPS:636
String userPassword = Constants.SPE1 + pwd + Constants.SPE1;
byte[] encodePwd = null;
encodePwd = userPassword.getBytes(StandardCharsets.UTF_16LE);
return encodePwd;
}
4.4
javax.naming.OperationNotSupportedException: [LDAP: error code 53 - 0000052D:
这是由于“密码不能满足密码策略的要求”导致,解决方案:
- 打开域安全策略-安全设置-账户策略-密码策略-密码必须符合复杂性要求。定义这个策略设置为:已禁用。/ 密码长度最小值:定义这个策略设置为0。
- 打开域控制器安全策略-安全设置-账户策略-密码策略-密码必须符合复杂性要求。定义这个策略设置为:已禁用。/ 密码长度最小值:定义这个策略设置为0。
- 最后运行刷新组策略命令为:gpupdate /force