【问题标题】:Active Directory Password reset without SSL没有 SSL 的 Active Directory 密码重置
【发布时间】:2017-01-11 04:14:09
【问题描述】:

我正在尝试在不使用 ssl 的情况下重置 Active Directory 用户的密码。通过这个link 了解可以在 AD 中禁用对 ssl 的需求。但是使用这段代码:

import javax.naming.*; 
import javax.naming.directory.*; 
import javax.naming.ldap.*; 
import java.util.*; 
import java.security.*; 
public class ADConnection { 
DirContext ldapContext; 
String baseName = ",cn=users,DC=fabrikam,DC=com"; 
String serverIP = "10.1.1.7"; 
public ADConnection() { 
try { 
Hashtable ldapEnv = new Hashtable(11); 
ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 
ldapEnv.put(Context.PROVIDER_URL, "ldap://" + serverIP + ":389"); 
ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple"); 
ldapEnv.put(Context.SECURITY_PRINCIPAL, "cn=administrator" + baseName); 
ldapEnv.put(Context.SECURITY_CREDENTIALS, "PA$$w0rd"); 
ldapContext = new InitialDirContext(ldapEnv); 
} 
catch (Exception e) { 
System.out.println(" bind error: " + e); 
e.printStackTrace(); 
System.exit(-1); 
} 
} 
public void updatePassword(String username, String password) { 
try { 
String quotedPassword = "\"" + password + "\""; 
char unicodePwd[] = quotedPassword.toCharArray(); 
byte pwdArray[] = new byte[unicodePwd.length * 2]; 
for (int i=0; i<unicodePwd.length; i++) { 
pwdArray[i*2 + 1] = (byte) (unicodePwd[i] >>> 8); 
pwdArray[i*2 + 0] = (byte) (unicodePwd[i] & 0xff); 
} 
ModificationItem[] mods = new ModificationItem[1]; 
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, 
new BasicAttribute("UnicodePwd", pwdArray)); 
ldapContext.modifyAttributes("cn=" + username + baseName, mods); 
} 
catch (Exception e) { 
System.out.println("update password error: " + e); 
System.exit(-1); 
} 
} 
public static void main(String[] args) { 
ADConnection adc = new ADConnection(); 
adc.updatePassword("Java User2", pass@word3); 
} 
}

结果:

javax.naming.OperationNotSupported: [LDAP: error code 53 - 00002077: SvcErr: DSID-03190F0A, problem 5003 (WILL_NOT_PERFORM)....

假设我们可以信任 Microsoft 文档(可以通过非 ssl 端口 389 重置密码),我怀疑 java API 并希望通过套接字建立与 AD 的直接连接并运行重置密码命令,实际上是在寻找javax.naming.* 的替代方案。那可能吗?有人试过在没有 ssl 的情况下重置 AD 密码吗?

P.S:Application Server 和 AD 服务器位于私有安全网络中,我不担心嗅探。

【问题讨论】:

  • Java 没有提供或设计该错误代码。广告做到了。寻找javax.naming 的替代品不会让您有任何收获。仔细查看错误消息的其余部分。
  • 谢谢,这是有道理的,但是,微软建议的所有“在不安全的连接上允许 passwd 操作”呢?
  • 您可以通过 TCP 389 重置密码,但首先您需要发出 STARTTLS 命令,该命令将会话的上下文切换为加密。无论哪种方式,除非您修改 dsHeuristics,否则您无法绕过 AD 中密码修改的 SSL 要求,当您可以发出 STARTTLS 并盲目接受证书时,这将是一种矫枉过正的做法(也有风险......您应该验证cert 是受信任的,但总比没有好......)。
  • 感谢@ChadSikorra,但我不知道如何通过 TCP 发送 AD 命令,也找不到教程或其他东西。是否仍应通过 javax.naming 完成?
  • STARTTLS 命令不是 AD,它是 LDAP 协议的一部分。我不是 Java 程序员,但这看起来像一个例子:docs.oracle.com/javase/7/docs/api/javax/naming/ldap/…

标签: java active-directory ldap


【解决方案1】:

Windows 不允许通过普通 ldap 更改 Active Directory 中的密码。 它需要有 SSL 连接才能更改 AD 存储密码的 unicodePwd 属性。

有时您可能会遇到以下异常:

javax.naming.OperationNotSupportedException: [LDAP: error code 53 - 00002077: SvcErr: DSID-03190F4C, problem 5003 (WILL_NOT_PERFORM), data 0 ]

解决方案:使用 SSL 证书

为了修改此属性,客户端必须与服务器建立 128 位传输层安全 (TLS)/安全套接字层 (SSL) 连接。只要满足最小密钥长度,使用 SSP 创建的使用 NTLM 或 Kerberos 的会话密钥的加密会话也是可以接受的。

Further reading

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多