簡體   English   中英

密碼重置使用UnboundID強制執行目錄策略

[英]Password Reset Enforcing Directory Policies with UnboundID

我正在開發一個Web應用程序,讓用戶可以在Active Directory中重置自己的密碼。 我一直在通過綁定作為管理員來做它並且它工作正常,但目錄策略(重用歷史,字符等)沒有被強制執行。 我無法綁定為用戶,因為我沒有當前密碼。

我讀到了Windows 2008 R2 SP1中引入的LDAP_SERVER_POLICY_HINTS控件,用於在Active Directory中執行此操作,甚至找到了使用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的最佳方法是什么? 相同的班級或不同的班級?

我不是那么熟悉微軟特定的控件,所以我不能在那里提供很多幫助,但看起來你已經在正確的軌道上了。 在這種情況下,它實際上看起來控件正在按預期工作,服務器拒絕密碼,因為它不夠強大。

Active Directory非常糟糕,因為它可以很難解決這個問題,但秘訣在於診斷消息中給出的“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。 UnboundID LDAP SDK for Java使這非常簡單,因為您可以使用LDAPConnection.getRootDSE方法檢索根DSE,然后使用RootDSE.supportsControl方法來確定服務器是否支持指定的控件。

關於是否處理具有相同類或不同類的不同OID的問題,這更多的是風格問題而不是其他問題。 如果具有較新OID的控件也對該值使用不同的編碼,那么這肯定會建議創建一個單獨的類。 如果兩個OID的值編碼相同,那么它可能是個人偏好的問題,但即使你將它們分成不同的類,那么最好保持大部分代碼的通用,而不是在兩個不同的地方使用相同的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM