Source Code: Java Active Directory Source Code
We will show the needed steps in order to do a java program that interacts with the Active Directory. This program must allow the following:
- Create user – with password that expired and does not expired.
- Enable user
- Disable user
- Login user
- Add user to a Group
- Show all users
After checking these requirements it is clear that we need to do the following task in order to achieve the solution:
Configuration
Configure secure connection (ldaps) in Active Directory
To change anything in the Active Directory we must go via secure connection (ldaps://your.ldap.server:636) so it is needed to enable the “ldaps” that normally listen in the port: “636”. The easiest way to do this is to install the Online Responder (Go to "Deploying Microsoft Online Responder" Section).
After installing use the program “ldp.exe” to check if it is possible to connect to the AD using SSL.
Add the Server Certificate to our Java key Store
If we run our java program we will get the error "unable to find valid certification path to requested target" because our server certificate is not issued by a certification authority.
To solve this we need to add the server certificate to our trusted Java key store. The easiest way is to run the program:InstallCert check more details about how to do this here.
Development
We will use the Spring-Ldap.
Spring Configuration
1: "1.0" encoding="UTF-8"?>
2: "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
3:
4:"contextSource"
5: class="org.springframework.ldap.core.support.LdapContextSource">
6:
7:"url" value="ldaps://192.168.1.102:636"/>
8:"base" value="CN=Users,dc=agileworks,dc=com"/>
9:"userDn" value="CN=Administrador,CN=Users,DC=agileworks,DC=com"/>
10:"password" value="$awpassword191"/>
11:"referral" value="follow"/>
12:"baseEnvironmentProperties">
13:
14:"java.naming.security.authentication" value="simple"/>
15:
16:
17:
18:"ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
19:"contextSource"/>
20:
21:"ldapUser" class="com.aw.ad.UserDaoImpl">
22:"ldapTemplate" ref="ldapTemplate"/>
23:
24:
Line 7: Using “ldaps” because we need to create users and change passwords.
Line 21: Configuring the DAO that will contain all the logic to interact with the AD
Getting reference to the UserDao
Resource resource = new ClassPathResource("springldap.xml");
BeanFactory factory = new XmlBeanFactory(resource);
UserDao userDao = (UserDaoImpl) factory.getBean("ldapUser");
Constants of the UserDao
// Attribute names
private static final String USER_ACCOUNT_CONTROL_ATTR_NAME = "userAccountControl";
private static final String PASSWORD_ATTR_NAME = "unicodepwd";
private static final String DISTINGUISHED_NAME_ATTR_NAME = "distinguishedname";
private static final String MEMBER_ATTR_NAME = "member";
// usercontrol params
private static final int FLAG_TO_DISABLE_USER = 0x2;
private static final int ADS_UF_DONT_EXPIRE_PASSWD = 0x10000;
private static final int USER_CONTROL_NORMAL_USER = 512;
Creating user
With password that expires
String userName = "Test18";
String pwd = "##12345xx";
User newUser = new User();
newUser.setUserName(userName);
newUser.setPassword(pwd);
userDao.createUser(newUser);
With password that does not expire
User newUser = new User();
newUser.setUserName(userName);
newUser.setPassword(pwd);
newUser.setExpirePasswd(false);
userDao.createUser(newUser);
UserDao.createUser method
1: public void createUser(User user) {
2: try {
3: Attributes userAttributes = new BasicAttributes();
4: userAttributes.put("objectclass", "person");
5: userAttributes.put("objectclass", "user");
6: userAttributes.put("userPrincipalName", user.getEmailAddress());
7: userAttributes.put("sAMAccountName", user.getUserName());
8: userAttributes.put("givenName", user.getFirstName());
9: userAttributes.put("sn", user.getLastName());
10: userAttributes.put("displayName", user.getDisplayName());
11: int userAccounControl = getUserAccountControl(user);
12: userAttributes.put("userAccountControl", "" + userAccounControl);
13: userAttributes.put("unicodepwd", encodePassword(user.getPassword()));
14: ldapTemplate.bind(getDnFrom(user.getUserName()), null, userAttributes);
15: } catch (NameAlreadyBoundException e) {
16: throw new DuplicateUserException("User:[" + user.getUserName() + "] allready exists in AD.", e);
17: } catch (OperationNotSupportedException e) {
18: throw new PasswordStrengthException("Password:[" + user.getPassword() + "] does not pass the strength password validation.", e);
19: } catch (Throwable e) {
20: throw new LdapException("Problems creating user.", e);
21: }
22: }
Line 1-13: Setting the user attributes.
Line 11: Getting the value of the userAccountControl that it is used to set different characteristics for the account. In our case we set here the type of the account and if the password will expire or not:
private int getUserAccountControl(User user) {
int userAccounControl = USER_CONTROL_NORMAL_USER;
if (!user.isExpirePasswd()) {
userAccounControl |= ADS_UF_DONT_EXPIRE_PASSWD;
}
return userAccounControl;
}
private byte[] encodePassword(String password) throws UnsupportedEncodingException {
String newQuotedPassword = "/"" + password + "/"";
return newQuotedPassword.getBytes("UTF-16LE");
}
Enable User
userDao.enableUser(userName);
UserDao.enableUser method
In order to enable the user the value of the userAccountControl must be change.
public void enableUser(String userName) {
DirContextOperations userContextOperations = ldapTemplate.lookupContext(getDnFrom(userName));
String userAccountControlStr = userContextOperations.getStringAttribute(USER_ACCOUNT_CONTROL_ATTR_NAME);
int newUserAccountControl = Integer.parseInt(userAccountControlStr) & ~FLAG_TO_DISABLE_USER;
userContextOperations.setAttributeValue(USER_ACCOUNT_CONTROL_ATTR_NAME, "" + newUserAccountControl);
ldapTemplate.modifyAttributes(userContextOperations);
}
Disable user
userDao.disableUser(userName);
UserDao.disableUser method
In order to disable the user the value of the userAccountControl must be change.
public void disableUser(String userName) {
DirContextOperations userContextOperations = ldapTemplate.lookupContext(getDnFrom(userName));
String userAccountControlStr = userContextOperations.getStringAttribute(USER_ACCOUNT_CONTROL_ATTR_NAME);
int newUserAccountControl = Integer.parseInt(userAccountControlStr) | FLAG_TO_DISABLE_USER;
userContextOperations.setAttributeValue(USER_ACCOUNT_CONTROL_ATTR_NAME, "" + newUserAccountControl);
ldapTemplate.modifyAttributes(userContextOperations);
}
Login user
userDao.login(userName, pwd)
UserDao.login method
public boolean login(String userName, String password) {
AndFilter filter = new AndFilter();
filter.and(new EqualsFilter("objectclass", "person")).and(new EqualsFilter("cn", userName));
return ldapTemplate.authenticate(DistinguishedName.EMPTY_PATH, filter.toString(), password);
}
Add user to a Group
userDao.addUserToGroup(userName, "AWGrupo1");
UserDao.addUserToGroup method
In order to assign a user to a specific Group in the AD we need to get a reference to the group and add the new user to its attribute “member”,
1: public void addUserToGroup(String userName, String group) {
2: try {
3: DirContextAdapter dirContext = (DirContextAdapter) ldapTemplate.lookup(getDnFrom(userName));
4: String dnUserFull = dirContext.getStringAttribute(DISTINGUISHED_NAME_ATTR_NAME);
5: DirContextOperations groupContextOperations = ldapTemplate.lookupContext(getDnFrom(group));
6: String[] currentMembers = groupContextOperations.getStringAttributes(MEMBER_ATTR_NAME);
7: ListdnUserFullList = new ArrayList ();
8: if (currentMembers != null && currentMembers.length > 0) {
9: dnUserFullList.addAll(Arrays.asList(currentMembers));
10: }
11: dnUserFullList.add(dnUserFull);
12: groupContextOperations.setAttributeValues(MEMBER_ATTR_NAME, dnUserFullList.toArray(new String[dnUserFullList.size()]));
13: ldapTemplate.modifyAttributes(groupContextOperations);
14: } catch (Throwable e) {
15: throw new LdapException("Problem adding user:[" + userName + "] to Group:[" + group + "]", e);
16: }
17: }
Line 4: Getting the full DN for the user that will be added to the group.
Line 5: Getting a reference to the Group
Line 6: Getting the list of current users of the Group
Line 11: Adding the user to the others users of the Group
Line 12: Setting the attribute “member” with the new list of users
Line 13: Saving the modifications.
Show all users
ListallUsers = userDao.getAllUsers();
System.out.println("There are:[" + allUsers.size() + "] users");
for (User user : allUsers) {
System.out.println(user);
}
UserDao.getAllUsers method
We will use a ContextMapper in order to populate the User info with the values that the AD will return.
public ListgetAllUsers() {
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
return ldapTemplate.search("", "(objectclass=person)", controls, new UserContextMapper());
}
public class UserContextMapper extends AbstractContextMapper {
@Override
protected Object doMapFromContext(DirContextOperations context) {
User user = new User();
user.setUserName(context.getStringAttribute("cn"));
user.setFirstName(context.getStringAttribute("givenName"));
user.setLastName(context.getStringAttribute("sn"));
user.setEmailAddress(context.getStringAttribute("userPrincipalName"));
user.setMemberOf(context.getStringAttribute("memberOf"));
user.setDisplayName(context.getStringAttribute("displayName"));
return user;
}
}
Tags: ActiveDirectory, AD, java, SpringLDAP