Java通过LDAP对接AD跨信任域认证报错错误码49(52e)问题咨询
问题原因
你遇到的LDAP错误码49带data 52e是AD域默认的「凭证无效」返回,但当前场景下属于跨域认证的配置问题,并非真的账号密码错误,核心问题有两个:
SECURITY_PRINCIPAL格式不符合跨域认证要求
AD跨域信任场景下,DN格式的Principal(cn=xxx,ou=xxx...)只能在用户归属的本地域(也就是AD2)生效,通过AD1做跨域认证时,AD1无法识别这种DN格式的用户标识,必须换成 用户主体名称(UPN) 或者 <域名><sAMAccountName> 格式,这也是你用AD Explorer能正常登录的原因——AD Explorer默认会把输入的账号转成UPN或者域\账号格式发起请求。- Simple认证的跨域兼容性问题
部分AD域的跨域信任配置默认不支持Simple认证的跨域传递,要么需要开启对应配置,要么改用LDAPS(带SSL的LDAP)连接AD1,因为Simple认证是明文传输密码,跨域场景下AD的安全策略可能会直接拦截请求。
解决方案
按以下步骤修改代码即可:
- 替换Principal格式
把原有SECURITY_PRINCIPAL的DN配置,替换为两种格式任选:- UPN格式:
env.put(Context.SECURITY_PRINCIPAL, "s***.u***@p***.net");(后缀为AD2的域后缀,和你原有DN里的dc配置对应即可) - 域\账号格式:
env.put(Context.SECURITY_PRINCIPAL, "P***\\s***.u***");(注意Java里反斜杠需要转义,前缀为AD2的NetBIOS域名)
- UPN格式:
- 可选适配项:如果修改Principal后还是报错,开启LDAPS连接
找客户索要AD1的根证书,导入到Java应用的信任库,把PROVIDER_URL改成ldaps://10.254.***.***:636,同时添加SSL配置:env.put(Context.SECURITY_PROTOCOL, "ssl");
如果认证成功后还需要查询AD2的用户数据,再添加referral跳转配置即可:
env.put(Context.REFERRAL, "follow");
修改后的完整示例代码如下:
Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://10.254.***.***:389"); // 用LDAPS的话端口换为636 env.put(Context.SECURITY_AUTHENTICATION, "Simple"); // 替换为UPN格式的Principal env.put(Context.SECURITY_PRINCIPAL, "s***.u***@p***.net"); env.put(Context.SECURITY_CREDENTIALS, "******"); // 跨域查询需要加的配置,仅做认证可以不加 env.put(Context.REFERRAL, "follow"); // 用LDAPS的话取消注释下面这行 // env.put(Context.SECURITY_PROTOCOL, "ssl"); try { DirContext ctx = new InitialDirContext(env); System.out.println("connected"); System.out.println(ctx.getEnvironment()); // 后续业务逻辑 ctx.close(); } catch (AuthenticationNotSupportedException ex) { System.out.println("The authentication is not supported by the server"+ex); } catch (AuthenticationException ex) { System.out.println("incorrect password or username"+ex); } catch (NamingException ex) { System.out.println("error when trying to create the context"+ex); }
内容的提问来源于stack exchange,提问作者Malik
相关产品推荐
相关产品推荐

