OpenLDAP的密码控制策略很强大,可以控制:
具体ppolicy的规格细节参考:http://www.zytrax.com/books/ldap/ch6/ppolicy.html
下面是本项目配置的默认策略:
# Default Policies
dn: cn=default,ou=policies,dc=xxxx,dc=cn
cn: default
objectClass: top
objectClass: device
objectClass: pwdPolicy
objectClass: pwdPolicyChecker
pwdAllowUserChange: TRUE
pwdAttribute: userPassword
#通过pwdCheckModule检查密码质量, 0为不控制,由SSO的认证模块自己控制
pwdCheckQuality: 0
#密码失效提前7天警告
pwdExpireWarning: 604800
#密码失败次数复位时间,1天
pwdFailureCountInterval: 86400
#密码过期不允许登录
pwdGraceAuthNLimit: 0
#保存密码历史3次,新密码不能与之相同
pwdInHistory: 3
#超过最多失败次数账号被锁定
pwdLockout: TRUE
#锁定后不能自动解锁,必须由管理员解锁
pwdLockoutDuration: 0
#密码有效期3个月
pwdMaxAge: 7776000
#密码最大失败次数,超过后被账号锁定
pwdMaxFailure: 5
pwdMinAge: 0
#密码最小长度
pwdMinLength: 8
pwdMustChange: FALSE
pwdSafeModify: FALSE
pwdChangedTime: last-password-change-time
#密码必须由管理员重置
pwdReset: TRUE
以上配置保存后ppolicy.ldif,导入到OpenLDAP中。
注意要实施密码策略,必须在OpenLDAP的slapd.conf中进行配置:
#装载security policy模块
moduleload ppolicy.la
# 密码加密算法
password-hash {SSHA}
#默认密码控制策略,关联上面的default ppolicy
overlay ppolicy
ppolicy_default "cn=default,ou=policies,dc=xxxx,dc=cn"
#Add和Modify中传递的密码明文在保存数据库中必须进行Hash加密
ppolicy_hash_cleartext
#此选项更改密码策略应答AccountLocked错误代码,而不是普通的InvalidCredentials
ppolicy_use_lockout
其中有一个校验用户修改的新密码不能在History中,这个一直有问题,后来在一个资料中发现下面的一段话:
No history checking occurs if the password is being modified by the rootdn
, although the password is saved in the history.
原来通过rootdn账号来修改密码,策略是不管用的。
同时必须在slapd.conf里面增加访问控制的配置:
#控制允许自己修改自己的Entry,匿名登录及允许所有用户可以读取
access to *
by self write
by anonymous auth
by * read
如果为了安全可以进一步按照下面的参考进行修改:
http://www.openldap.org/doc/admin24/access-control.html
下面是认证和修改密码的测试代码:
@Test
public void testChgPwd() throws NamingException, UnsupportedEncodingException {
String dn = "uid="+sUserName+","+base;
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, sp);
env.put(Context.PROVIDER_URL, ldapUrl);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, dn);
env.put(Context.SECURITY_CREDENTIALS, oldPwd);
dctx = new InitialDirContext(env);
ModificationItem[] mods = new ModificationItem[1];
System.out.println("modification item");
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("userPassword", newPwd));
dctx.modifyAttributes(dn, mods);
}
如果修改的密码是在pwdHistory里面就会抛出19异常:
javax.naming.directory.InvalidAttributeValueException: [LDAP: error code 19 - Password is in history of old passwords];