优质广告供应商

广告是为了更好地支持作者创作

OpenLDAP的密码策略实现

OpenLDAP的密码控制策略很强大,可以控制:

  1. 密码的生命周期(最大和最小值);
  2. 保存密码历史,避免在一段时间内重用相同的密码;
  3. 密码强度,新密码可以根据各种特性进行检查;
  4. 密码连续认证失败的最大次数;
  5. 自动账号锁定;
  6. 支持自动或管理员解锁账号;
  7. 优雅(Grace)绑定(允许密码失效后登录的次数);
  8. 密码策略可以在任意DIT范围定义,可以是用户、组或任意组合。

具体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];

优质广告供应商

广告是为了更好地支持作者创作

推荐阅读更多精彩内容