My scenario is similar to what's described in this question How to authenticate users with a customer's (remote) active directory server , except that our web application is Java based and runs under CentOS Linux.
I have been searching and reading a lot, but don't seem to be able to find useful information for my scenario because of the following:
Now based on my recent reading, best security practices are for organizations to hide Active Directory server behind firewall and do not expose it to the Internet. I wonder whether that means there will not be "direct" path of remote Active Directory authentication integration regardless of tools and libraries, and some kind of trusted agent or proxy residing within the customer infrastructure will be required to facilitate the remote authentication.
Any comments and suggestions are welcome!
We can access remote AD via LDAP protocol. In my scenario, I have LDAP configured on remote server. I have installed Apache Active DS to create an instance of remote directory at my end. So I can have a configuration details at my end. To do this we require domain name & bind credentials . You can download Apache Directory for Linux from this link & create new connection. See LDAP Connections to Active Directory Using Apache Directory Studio
LDAP Configuration for Tomcat :
Sample JNDIRealm configuration for Tomcat 7 - Apache.org
Add your desired Realm configuration between Host opening and Host closing tag in server.xml file located at conf directory of Tomcat. eg,
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Realm className="org.apache.catalina.realm.JNDIRealm"
connectionName="cn=Manager,dc=mycompany,dc=com"
connectionPassword="secret"
connectionURL="ldap://localhost:389"
userPassword="userPassword"
userPattern="uid={0},ou=people,dc=mycompany,dc=com"
roleBase="ou=groups,dc=mycompany,dc=com"
roleName="cn"
roleSearch="(uniqueMember={0})"
/>
<!-- other stuffs -->
</Host>
Don't forget to comment out the below entry in server.xml file.
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
Once you are done with this then it's time to configure your web application which will give a call to LDAP server via Tomcat server.
Web Application Configuration :
Add below entries in your web.xml file placed inside WebContent -> WEB-INF
directory.
<security-constraint>
<web-resource-collection>
<web-resource-name>Logging Area</web-resource-name>
<description>
Authentication Required.
</description>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>*</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Authentication Required.</realm-name>
</login-config>
This is the basic configuration. But, you can map specific user or group with LDAP . Have a look at Mapping Roles to Users and Groups - J2EE Tutorial . You can also add security to specific folder only, by adding url pattern for it under web-resource-collection
tags.
<url-pattern>/Admin/*</url-pattern> // Restrict access to Admin folder
<url-pattern>/Employee/*</url-pattern> // Restrict access to Employee folder
All configuration are done. Now, when your run you application it will ask for Login Credentials . Once you enter & hit submit it will search for that user in LDAP server.
At server, to get access to user name use below code snippet :-
Principal principal = request.getUserPrincipal();
String userName = principal.getName();
Example LDAP User Manager (JBOSS):
public LdapContext getLdapContext() {
// Set up environment for creating initial context
Hashtable<String, Object> env = new Hashtable<String, Object>(11);
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
// e.g., ldap://IP address of remote m/c:10389/dc=sevenseas,dc=com
env.put(Context.PROVIDER_URL, LDAP_PROVIDER_URL + Constant.FORWARD_SLASH + LDAP_DOMAIN);
// Authenticate as User and password
env.put(Context.SECURITY_AUTHENTICATION, "simple");
// e.g., "uid=admin,ou=system"
env.put(Context.SECURITY_PRINCIPAL, LDAP_ADMIN);
env.put(Context.SECURITY_CREDENTIALS, LDAP_DEFAULT_PASSWORD);
try {
// Create initial context
ldapContext = new InitialLdapContext(env, null);
if (ldapContext == null) {
LogManager.fatal("Invalid LDAP system properties. Please contact your administrator.",
LDAPUserManager.class.getName());
}
System.out.println("Organization : " + ldapContext.getNameInNamespace());
} catch (Exception e) {
StringWriter stack = new StringWriter();
e.printStackTrace(new PrintWriter(stack));
LogManager.fatal(stack.toString(), LDAPUserManager.class.getName());
}
return ldapContext;
}
This will Construct initial context with environment parameters to connect with LDAP server.
Now, to fetch user data from AD use the below code :
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
String[] attrIDs = { "cn", "sn", "givenName", "uid", "mail", "userPassword" };
constraints.setReturningAttributes(attrIDs);
// Search for user in LDAP server by emailId
NamingEnumeration<SearchResult> answer = ldapContext.search(LDAP_GROUP, "mail=" + emailId, constraints);
if (answer.hasMore()) {
LogManager.info("User with email id '" + emailId + "' found.", LDAPUserManager.class.getName());
Attributes attrs = answer.next().getAttributes();
userDTO = new UserDTO();
// Store user details temporarily
Attribute firstNameAttr = attrs.get("givenName");
String firstName = "";
if (firstNameAttr == null) {
userDTO.setFirstName(firstName);
} else {
firstName = firstNameAttr.get().toString();
if (firstName == null) {
userDTO.setFirstName("");
}
userDTO.setFirstName(firstName);
}
Attribute lastNameAttr = attrs.get("sn");
String lastName = "";
if (lastNameAttr == null) {
userDTO.setLastName(lastName);
} else {
lastName = lastNameAttr.get().toString();
if (lastName == null) {
userDTO.setLastName("");
}
userDTO.setLastName(lastName);
}
return userDTO;
} else {
LogManager.fatal("Invalid User.", LDAPUserManager.class.getName());
return userDTO;
}
} catch (Exception e) {
StringWriter stack = new StringWriter();
e.printStackTrace(new PrintWriter(stack));
LogManager.fatal(stack.toString(), LDAPUserManager.class.getName());
}
I hope this helps you.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.