Dear Chun-Yao,
Apache DS is LDAP Server. In all LDAP Server - including the implementation of LDAP by Microsoft - which is called Active Directory - have the feature of Password Policies. [Pl see -
https://ldapwiki.com/wiki/Password%20Policy]
These can be easily configured in the Directory Studio Admin - by opening the configuration file - going to Password Policies Tab. Pl see the screenshot enclosed below [red indicates the parameters in your case to be added to the system].
The CAS properties that i used for getting the application up and running are given below. [version 6.2.x for CAS].
#########local LDAP Connection String for authentication using the Managers Bind Tested as OK on localhost.#################
cas.authn.ldap[0].ldapUrl=ldap://localhost:389/
cas.authn.ldap[0].bindDn=uid=admin,ou=system
cas.authn.ldap[0].bindCredential=xxxx
cas.authn.ldap[0].poolPassivator=BIND
#cas.authn.ldap[0].connectionStrategy=DEFAULT
#cas.authn.ldap[0].providerClass=org.ldaptive.provider.unboundid.UnboundIDProvider
cas.authn.ldap[0].type=AUTHENTICATED
#cas.authn.ldap[0].useSsl=false
cas.authn.ldap[0].useStartTls=false
cas.authn.ldap[0].baseDn=dc=tbitslocal,dc=com
cas.authn.ldap[0].subtreeSearch=true
cas.authn.ldap[0].searchFilter=(&(objectClass=person)(uid={user}))
cas.authn.ldap[0].principalAttributeList=sn,cn:commonName,displayName,l,o,postalAddress,mail,mobile,ou
cas.authn.ldap[0].minPoolSize=3
cas.authn.ldap[0].maxPoolSize=10
cas.authn.ldap[0].blockWaitTime=PT3S
#cas.authn.ldap[0].useSsl=false
cas.authn.ldap[0].useStartTls=false
cas.authn.ldap[0].responseTimeout=PT5S
cas.authn.ldap[0].allowMultipleDns=false
cas.authn.ldap[0].allowMultipleEntries=false
cas.authn.ldap[0].followReferrals=false
cas.authn.ldap[0].name=localhostLDAP
#################LDAP Password Policy##############################
cas.authn.ldap[0].passwordPolicy.type=GENERIC
cas.authn.ldap[0].passwordPolicy.enabled=true
cas.authn.ldap[0].passwordPolicy.policyAttributes.accountLocked=javax.security.auth.login.AccountLockedException
cas.authn.ldap[0].passwordPolicy.loginFailures=5
#cas.authn.ldap[0].passwordPolicy.warningAttributeValue=
#cas.authn.ldap[0].passwordPolicy.warningAttributeName=
cas.authn.ldap[0].passwordPolicy.displayWarningOnMatch=true
cas.authn.ldap[0].passwordPolicy.warnAll=true
cas.authn.ldap[0].passwordPolicy.warningDays=1
cas.authn.ldap[0].passwordPolicy.accountStateHandlingEnabled=true
#############Properties for LDAP Password Management############
cas.authn.pm.ldap[0].type=GENERIC
cas.authn.pm.ldap[0].username-attribute=uid
cas.authn.pm.ldap[0].ldapUrl=ldap://localhost:389/
cas.authn.pm.ldap[0].bindDn=uid=admin,ou=system
cas.authn.pm.ldap[0].bindCredential=xxxx
cas.authn.pm.ldap[0].poolPassivator=BIND
cas.authn.pm.ldap[0].connectionStrategy=RANDOM
cas.authn.pm.ldap[0].connect-timeout=PT5S
#cas.authn.pm.ldap[0].providerClass=org.ldaptive.provider.unboundid.UnboundIDProvider
#cas.authn.pm.ldap[0].type=AUTHENTICATED
#cas.authn.pm.ldap[0].useSsl=false
cas.authn.pm.ldap[0].useStartTls=false
cas.authn.pm.ldap[0].baseDn=dc=tbitslocal,dc=com
cas.authn.pm.ldap[0].subtreeSearch=true
cas.authn.pm.ldap[0].searchFilter=(&(objectClass=person)(uid={user}))
#cas.authn.pm.ldap[0].principalAttributeList=sn,cn:commonName,displayName,l,o,postalAddress,mail,mobile
cas.authn.pm.ldap[0].minPoolSize=3
cas.authn.pm.ldap[0].maxPoolSize=10
cas.authn.pm.ldap[0].blockWaitTime=PT3S
#cas.authn.pm.ldap[0].useSsl=false
cas.authn.pm.ldap[0].useStartTls=false
cas.authn.pm.ldap[0].responseTimeout=PT5S
cas.authn.pm.ldap[0].allowMultipleDns=false
cas.authn.pm.ldap[0].allowMultipleEntries=false
cas.authn.pm.ldap[0].followReferrals=false
cas.authn.pm.ldap[0].name=localhostLDAP_PM_Feature
#######################
Some words of advice - to save time
1. While dealing with LDAP - pl test all your settings using the commandline first before using them for configuration in CAS. Execute the basic commands etc "ldapsearch" using your settings - first using the command line to ensure that your connections and values are working - before filling in the CAS properties as applicable in your case.
2. Pll don't blindly copy paste cas properties - think and understand what you are doing.
3. The only constraint that faced was that at the time of :"forget username" or "forget password" - there can be only be a single search query that can be defined - if you integrate with LDAP as against JDBC, where you can define 2 different queries - one for getting usename and another for fetching the email address etc. I overcame the above constraint - but setting the username = email , for my use case.
4. Before implementing a Directory Services as LDAP / ApacheDS - think if you already have access to your LDAP or any other directory services internally. All Standard Directory Services will offer you Password Policies Features, better use them before introducing a new software in your organization.
Please feel free to contact me - if you have any further questions.
Best Regards & Best Wishes for New Year 2021!
Ritesh Tripathi