公司使用的是2008版的Active Directory。
使用java去链接08版的windows修改08版的AD密码。密码策略有如下6种:
我们需要实现的是前5种。我们使用spring-ldap去做操作访问。
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
</dependency>
有两种方法:updateCredentialToAd()和change()。而reset只会校验第4、5两条规则(length and complexity)。changeCredentialToAd()会校验所有5条规则!
刚开始一直使用reset密码,history策略总是不生效,后面google后才明白,原来有change密码功能!
上面大多数是用PHP写的代码,java写的参考此处:java changePassword
public void updateCredentialToAd(String ownerId, String plainTextPassword)
throws UnsupportedEncodingException {
UserAD user = adUserInfoDao.getUserInfoById(ownerId);
ProfileServiceAssert.notNull(user, ProfileServiceExceptionEnum.USER_NOT_FOUND_AD, ownerId);
Name dn = LdapNameBuilder.newInstance(user.getDn()).build();
Attribute newAttr = new BasicAttribute("unicodePwd",
("\"" + plainTextPassword + "\"").getBytes(StandardCharsets.UTF_16LE));
ModificationItem replaceItem = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, newAttr);
ldapTemplate.modifyAttributes(dn, new ModificationItem[] {replaceItem});
}
public void changeCredentialToAd(String ownerId, String plainOldPassword,String plainTextPassword){
UserAD user = adUserInfoDao.getUserInfoById(ownerId);
ProfileServiceAssert.notNull(user, ProfileServiceExceptionEnum.USER_NOT_FOUND_AD, ownerId);
Name dn = LdapNameBuilder.newInstance(user.getDn()).build();
Attribute oldAttr = new BasicAttribute("unicodePwd",
("\"" + plainOldPassword + "\"").getBytes(StandardCharsets.UTF_16LE));
Attribute newAttr = new BasicAttribute("unicodePwd",
("\"" + plainTextPassword + "\"").getBytes(StandardCharsets.UTF_16LE));
ModificationItem removeItem = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, oldAttr);
ModificationItem addItem = new ModificationItem(DirContext.ADD_ATTRIBUTE, newAttr);
ldapTemplate.modifyAttributes(dn, new ModificationItem[] {removeItem,addItem});
}
几个注意点:
1.修改密码后,AD是在10分钟(默认)后才会刷新,也就是说旧密码在10分钟内还是可以登陆使用的!如果要修改,这个就需要修改注册表了,很麻烦。
2.修改unicodePwd是需要用ssl加密连接来修改
踩到的坑,花较多时间的,想吐槽的是:
1.一直没明白password history与minimum password age 和 maximum password age关系。所以,搞了两天没明确把功能实现出来。问题也在于,官方文档对这三个策略的关系没有说完全:
Enforce password history: Enforce password history
直到看到个地方:Password Best practices
才明白了maximum/minimum pwd age与history的关系:
1.min age是新密码必须使用的时间,设置之后,在minimum age里reset/change都不能成功
2.max age是密码过期时间,过期了,密码都会进入history
3.history 个数包含当前正在使用的密码。比如: history=4,则包含前面过期的3个密码+当前正在使用的密码。
补充:
- 5种密码策略,返回的异常分两种:
//不符合密码复杂度和长度
OperationNotSupportedException.class
//不符合minimun pwd age 和 enforce password history
InvalidAttributeValueException.class
2.2012版,不能通过修改系统时间来进行测试password age的问题。
而2008版,我们是通过修改系统时间来测试,让pwd进入history的。