2014-01-15 63 views
1

我正在開發一個Web應用程序,讓用戶在Active Directory中重置自己的密碼。我一直以管理員身份進行綁定並且工作正常,但目錄策略(重用歷史記錄,字符等)未被強制執行。我無法以用戶身份綁定,因爲我沒有當前密碼。密碼重置使用UnboundID強制實施目錄策略

我讀到有關Windows 2008 R2 SP1控制引入做,在Active Directory中的LDAP_SERVER_POLICY_HINTS甚至發現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 = "[email protected]"; 
    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 
     ') 

研究了一下後,我越發現,有爲此改變了OID到1.2.840.113556.1.4.2066同一控制在Windows 2012的另一個更新和棄用老OID。

由於這個應用程序可以配置任何版本的AD我想優雅地處理每個場景(Windows 2012,Windows 2008 R2 SP1,其他)。我的問題是:

  1. 有沒有人用UnboundID成功做到這一點?
  2. 無論如何要知道在修改請求之前控件是否可用?
  3. 對於相同的控件,處理不同AD版本的不同OID的最佳方式是什麼?同一班還是不同班?

回答

3

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

活動目錄真的很糟糕,它使得這些東西變得非常困難,但祕密在於診斷信息中給出的「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相同,那麼它可能是個人喜好的問題,但即使你讓他們單獨的類那麼這將是很好的保持了大部分常見的代碼,而不是在兩個不同的地方相同的代碼。

+0

是的,你是對的,我用的密碼是不夠強大。現在起作用了。感謝這麼多的參考AD錯誤代碼和建議。 –