gpt4 book ai didi

java - 密码重置使用 UnboundID 执行目录策略

转载 作者:行者123 更新时间:2023-11-29 05:30:52 29 4
gpt4 key购买 nike

我正在开发一个网络应用程序,让用户可以在 Active Directory 中重置自己的密码。我一直通过以管理员身份进行绑定(bind)来做到这一点并且它工作正常,但是没有强制执行目录策略(重用历史记录,字符等)。我无法绑定(bind)为用户,因为我没有当前密码。

我阅读了 Windows 2008 R2 SP1 中引入的 LDAP_SERVER_POLICY_HINTS 控件,用于在 Active Directory 中执行此操作,甚至找到了 someone who made it using Spring LDAP

由于我使用的是 UnboundID 并且没有为此提供标准控件,所以我认为我必须创建自己的控件类。记录的 OID 是 1.2.840.113556.1.4.2239 和值 {48, 3, 2, 1, 1}

public class PolicyHintsControl extends Control {

private static final long serialVersionUID = 1L;

public final static String LDAP_SERVER_POLICY_HINTS_OID = "1.2.840.113556.1.4.2066";

public final static byte[] LDAP_SERVER_POLICY_HINTS_DATA = { 48,
(byte) 132, 0, 0, 0, 3, 2, 1, 1 };

public PolicyHintsControl() {
super(LDAP_SERVER_POLICY_HINTS_OID, false, new ASN1OctetString(
LDAP_SERVER_POLICY_HINTS_DATA));
}

@Override
public String getControlName() {
return "LDAP Server Policy Hints Control";
}

@Override
public void toString(StringBuilder buffer) {
buffer.append("LDAPServerPolicyHints(isCritical=");
buffer.append(isCritical());
buffer.append(')');
}
}

所以我在修改请求中添加了这个新控件,如下所示:

public static void main(String[] args) throws Exception {

final String host = "ldap.example.com";
final int port = 636;
String adminDn = "admin@example.com";
String adminPassword = "passwd";
String userDn = "CN=user,ou=people,dc=example,dc=com";
String userPassword = "passwd";
String keystoreFile = "/path/to/keystore.jks";
String keystorePassword = "passwd";

String passwordAttribute = "unicodePwd";

//Password change requires SSL
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(new FileInputStream(keystoreFile), keystorePassword.toCharArray());
TrustManagerFactory factory = TrustManagerFactory.getInstance("x509");
factory.init(keyStore);
final SSLUtil sslUtil = new SSLUtil(factory.getTrustManagers());
SSLSocketFactory socketFactory = sslUtil.createSSLSocketFactory();
Debug.setEnabled(true);

// Connect as the configured administrator
LDAPConnection ldapConnection = new LDAPConnection(socketFactory, host,
port, adminDn, adminPassword);
// Set password in AD format
final String newQuotedPassword = "\"" + userPassword + "\"";
final byte[] newPasswordBytes = newQuotedPassword.getBytes("UTF-16LE");
String encryptedNewPwd = new String(newPasswordBytes);
//Build modifications array and request
final ArrayList<Modification> modifications = new ArrayList<Modification>();
modifications.add(new Modification(ModificationType.REPLACE,
passwordAttribute, encryptedNewPwd));
ModifyRequest modifyRequest = new ModifyRequest(userDn, modifications);
//Add the policy hints control
modifyRequest.addControl(new PolicyHintsControl());
//Modify already
ldapConnection.modify(modifyRequest);
ldapConnection.close();
}

我得到以下异常:

Exception in thread "main" LDAPException(resultCode=53 (unwilling to perform), errorMessage='0000052D: SvcErr: DSID-031A120C, problem 5003 (WILL_NOT_PERFORM), data 0
', diagnosticMessage='0000052D: SvcErr: DSID-031A120C, problem 5003 (WILL_NOT_PERFORM), data 0
')

经过更多研究后,我发现 Windows 2012 中有针对同一控件的另一个更新,将 OID 更改为 1.2.840.113556.1.4.2066 并弃用了旧的 OID。

由于此应用程序可以配置任何版本的 AD,我想优雅地处理每个场景(Windows 2012、Windows 2008 R2 SP1 等)。我的问题是:

  1. 有没有人用 UnboundID 成功地做到了这一点?
  2. 有没有办法知道在修改请求之前控件是否可用?
  3. 为同一控件的不同版本的 AD 处理不同 OID 的最佳方法是什么?同类还是不同类?

最佳答案

我不太熟悉 Microsoft 特定的控件,因此我无法在这方面提供很多帮助,但看起来您已经走上了正确的轨道。在这种情况下,控件实际上看起来像预期的那样工作并且服务器拒绝密码,因为它不够强。

Active Directory 真的很糟糕,因为它很难解决这样的问题,但 secret 在于诊断消息中给出的“0000052D”。这是对 Active Directory 系统错误代码 0x52D 的引用,它是十进制的 1325。系统错误代码记录在 http://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx 中。 ,在这种情况下,您需要点击“系统错误代码 (1300-1699)”链接 (http://msdn.microsoft.com/en-us/library/windows/desktop/ms681385(v=vs.85).aspx) 并找到值 1325 的说明。该错误代码的文本显示“无法更新密码。该值提供的新密码不符合域的长度、复杂性或历史要求。”由于您尝试使用的控制点似乎是使服务器对新密码执行质量检查,因此它看起来像预期的那样工作。如果您使用更强的密码(例如,使其更长,包括大写/数字/符号字符等),那么服务器可能会接受它。

关于确定服务器支持哪些控件的问题,方法是检索服务器根 DSE 并查看 supportedControls 属性中报告的 OID。用于 Java 的 UnboundID LDAP SDK 使这变得非常简单,因为您可以使用 LDAPConnection.getRootDSE 方法检索根 DSE,然后使用 RootDSE.supportsControl 方法确定服务器是否支持指定的控件。

关于您是处理具有相同类还是不同类的不同 OID 的问题,这更像是一种风格问题,而不是其他任何问题。如果具有较新 OID 的控件也对值使用不同的编码,那么这肯定会建议创建一个单独的类。如果两个 OID 的值编码相同,那么这可能是个人偏好的问题,但即使您将它们设为单独的类,也最好保持大部分代码通用,而不是在两个不同的地方使用相同的代码.

关于java - 密码重置使用 UnboundID 执行目录策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21138911/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com