Java LDAPS连接AD域636端口报连接超时异常如何解决
Java LDAPS连接AD超时问题排查方案
问题说明
编写Java代码配置SSL,通过LDAPS协议连接Active Directory做管理员账号身份认证时,抛出连接异常,核心错误为javax.naming.CommunicationException,根因是TCP连接超时。
问题代码
public class Unicode_passwordLdap{ public static void main(String[] args){ LdapContext ctx = null; try{ Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); System.setProperty("javax.net.ssl.trustStore", "C://Java//jre1.8.0_331//lib//security//cacerts"); System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); System.setProperty("javax.net.ssl.keyStore", "C://Java//jre1.8.0_331//lib//security//cacerts"); System.setProperty("javax.net.ssl.keyStorePassword","changeit"); System.setProperty("javax.net.debug", "all"); String baseName = ",CN=Users,DC=trial,DC=com"; Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.SECURITY_AUTHENTICATION, "Simple"); env.put(Context.SECURITY_PRINCIPAL, "cn=administrator" + baseName); //"tom@trial.com" env.put(Context.SECURITY_CREDENTIALS, "admin1*"); //"Panda123*" env.put(Context.PROVIDER_URL, "ldaps://WS2K19.trail.com:636"); //dc=trial,dc=com //ldaps://WS2K19.trail.com:636 env.put(Context.SECURITY_PROTOCOL, "ssl"); ctx = new InitialLdapContext(env,null); System.out.println("Connection Successfull"); }catch(Exception e){ //System.out.println("Password Cannot be Changed"); e.printStackTrace(); } } }
异常栈信息
javax.naming.CommunicationException: WS2K19.trail.com:636 [Root exception is java.net.ConnectException: Connection timed out: connect] at com.sun.jndi.ldap.Connection.<init>(Connection.java:235) at com.sun.jndi.ldap.LdapClient.<init>(LdapClient.java:137) at com.sun.jndi.ldap.LdapClient.getInstance(LdapClient.java:1615) at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2847) at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:348) at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxFromUrl(LdapCtxFactory.java:225) at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:189) at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:243) at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:154) at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:84) at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:694) 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 Unicode_passwordLdap.main(Unicode_passwordLdap.java:63)
注意:
Connection timed out属于TCP三层/四层连通性故障,和SSL证书配置、账号密码正确性没有关系,排查优先从网络层面入手,不要一开始就调整SSL、账号相关参数浪费时间。
排查步骤(按优先级排序)
1. 先修正明显的拼写错误
代码中域配置为DC=trial,DC=com,但连接地址写的是WS2K19.trail.com,trial和trail拼写不一致,先确认真实域控的域名,统一所有位置的域名拼写。
2. 验证客户端到AD的636端口连通性
在运行Java程序的机器上执行端口探测:
- Windows环境:PowerShell执行
Test-NetConnection 域控地址 -Port 636,或者cmd执行telnet 域控地址 636 - Linux/macOS环境:执行
nc -zv 域控地址 636
如果探测结果为不通,直接定位为网络层问题,按以下方向排查: - 检查客户端DNS配置/hosts文件,确认域名解析到的IP是AD域控的真实业务IP,没有解析到无效地址
- 检查客户端本地防火墙、终端安全软件,确认没有拦截发往636端口的出站请求
- 检查中间链路的防火墙、交换机、安全组策略,确认客户端到域控636端口的TCP流量没有被拦截
- 登录AD域控本地,执行
netstat -ano | findstr :636,确认AD的LDAPS服务已经正常监听636端口:- 如果没有监听记录,说明AD端LDAPS没有配置完成,需要给域控导入服务器身份验证证书,重启NTDS服务后LDAPS才会生效
- 如果有监听记录,检查域控本地防火墙的入站规则,确认放通了636端口的入站访问
3. 排除非代码类问题后再调整代码
当端口连通性验证通过后,再调整代码里的冗余/错误配置:
- 删除JDK旧版SSL Provider加载语句:
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()),该配置仅适用于JDK1.5及更早版本,JDK1.8自带成熟的SSL实现,加载内部旧Provider反而可能引发兼容问题 - 移除不必要的keystore配置:LDAPS客户端连接场景下,仅需要配置truststore(存储信任的CA根证书),不需要配置keystore(keystore仅用于双向TLS认证时提供客户端证书),当前配置把keystore指向cacerts属于无效配置
- 若AD使用自签名证书搭建LDAPS,需要提前把AD的根CA证书导入到指定的truststore文件中,否则连通后会报SSL证书信任错误
- 调试阶段可以保留
javax.net.debug=all配置看SSL握手日志,验证通过后删除该配置避免输出冗余日志
验证流程
- 端口连通性探测通过后,先用系统自带工具验证LDAPS可用性:Windows用
ldp.exe连接636端口做绑定测试,Linux用ldapsearch命令行测试认证,确认账号密码、LDAPS服务本身正常 - 系统工具验证通过后,再运行调整后的Java代码测试连接
内容的提问来源于stack exchange,提问作者anandhu
相关产品推荐
相关产品推荐

