I have a code which authenticates, interacts with the Active Directory and fetches some information. But I just want to be sure that I close the connection and return it to the pool. How can I ensure them?
Here is my code:
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
public class LDAPExaminer {
public static void main(String[] args) {
LDAPExaminer ldapExaminer = new LDAPExaminer();
// NOTE: replace theUserName below with the Active Directory/LDAP user whose attribites you want printed.
ldapExaminer.printUserBasicAttributes("<strong>theUserName</strong>", ldapExaminer.getLdapContext());
}
public LdapContext getLdapContext() {
LdapContext ctx = null;
try {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "Simple");
// NOTE: replace user#domain.com with a User that is present in your Active Directory/LDAP
env.put(Context.SECURITY_PRINCIPAL, "<strong>user#domain.com</strong>");
// NOTE: replace userpass with passwd of this user.
env.put(Context.SECURITY_CREDENTIALS, "userpass");
// NOTE: replace ADorLDAPHost with your Active Directory/LDAP Hostname or IP.
env.put(Context.PROVIDER_URL, "ldap://ActiveDirOrLDAPHost:389");
System.out.println("Attempting to Connect...");
ctx = new InitialLdapContext(env, null);
System.out.println("Connection Successful.");
} catch (NamingException nex) {
System.out.println("LDAP Connection: FAILED");
nex.printStackTrace();
}
return ctx;
}
private void printUserBasicAttributes(String username, LdapContext ctx) {
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
// NOTE: The attributes mentioned in array below are the ones that will be retrieved, you can add more.
String[] attrIDs = { "distinguishedName", "sn", "givenname", "mail", "telephonenumber", "canonicalName",
"userAccountControl", "accountExpires" };
constraints.setReturningAttributes(attrIDs);
// NOTE: replace DC=domain,DC=com below with your domain info. It is essentially the Base Node for Search.
NamingEnumeration answer = ctx.search("DC=YourDomain,DC=com", "sAMAccountName=" + username, constraints);
if (answer.hasMore()) {
Attributes attrs = ((SearchResult) answer.next()).getAttributes();
System.out.println(attrs.get("distinguishedName"));
System.out.println(attrs.get("givenname"));
System.out.println(attrs.get("sn"));
System.out.println(attrs.get("mail"));
System.out.println(attrs.get("telephonenumber"));
System.out.println(attrs.get("canonicalName"));
System.out.println(attrs.get("userAccountControl"));
System.out.println(attrs.get("accountExpires"));
} else {
throw new Exception("Invalid User");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
a couple of things
1) possible duplicate of Java LDAP graceful disconnect
2) try adding this in the appropriate place(s) [in at least one catch and in main]
ctx.close();
if you're going to keep this function based, I'd write one more to put your 'main' code into, including the close().
Related
I am currently working on a project like this. When the username and password are entered, the check will be made via LDAP and if it is correct, I need to return a successful transaction, otherwise I want a failed transaction. In short, I will log in via LDAP. We have an ldap server ready now. We have an ldap server ready now. So domain, host, and searchBase have it all. But I'm trying to understand the logic, can I do this using Spring Boot? Because in most tutorials, the name and password are entered manually. But I want the input to be entered by any client, not manually, and check if it exists on my server. If such a thing is not possible in spring boot, how can I check the username and password values sent to the method by LDAP by verifying and returning them in the code we have written below?
package az.expressbank.ldap.test;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
*/
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
public class ControlDomainLogin {
private String domain;
private String ldapHost;
private String searchBase;
public ControlDomainLogin() {
this.domain = "domain.com";
this.ldapHost = "ldap://url";
this.searchBase = "DC=something,DC=com"; // YOUR SEARCH BASE IN LDAP
}
Map<String, Object> amap = null;
// public ADAuthenticator(String domain, String host, String dn)
// {
// this.domain = domain;
// this.ldapHost = host;
// this.searchBase = dn;
// }
public Map<String, Object> authenticate(String user, String pass) {
String[] returnedAtts = {"sn", "givenName", "name", "userPrincipalName", "displayName", "memberOf"};
String searchFilter = "(&(objectClass=User)(sAMAccountName=" + user + "))";
// Create the search controls
SearchControls searchCtls = new SearchControls();
searchCtls.setReturningAttributes(returnedAtts);
// Specify the search scope
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapHost);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, user + "#" + domain);
env.put(Context.SECURITY_CREDENTIALS, pass);
env.put(Context.SECURITY_PROTOCOL, "SSL");
LdapContext ctxGC = null;
NamingEnumeration<SearchResult> answer = null;
Attributes attrs = null;
SearchResult sr = null;
NamingEnumeration<?> ne = null;
Attribute attr = null;
try {
ctxGC = new InitialLdapContext(env, null);
answer = ctxGC.search(searchBase, searchFilter, searchCtls);
if (answer != null) {
while (answer.hasMoreElements()) {
sr = (SearchResult) answer.next();
attrs = sr.getAttributes();
if (attrs != null) {
amap = new HashMap<String, Object>();
ne = attrs.getAll();
attr = (Attribute) ne.next();
amap.put(attr.getID(), attr.get());
ne.close();
}
ctxGC.close(); // Close and clean up
}
} else {
System.out.println("Answer from domen controller is null!");
}
} catch (NamingException ex) {
System.out.println("Exception: " + ex.toString());
} finally {
System.out.println("");
}
return amap;
}
}
I want me to do this by creating an API. So I will call this method in my service layer and send my username and password there. My method successfully checks the username and password sent to it. For example
#Override
public Optional login(String username, String password, String type) {
/*
for example when I send username and password to the following method
*/
Map<String, Object> authenticate = controlDomainLogin.authenticate(username, password);
/*
I want to match the value of method of login of parametr returned from the following method of authenticate of returned value , if they match, I want to print the correct operation, otherwise the wrong input operation.
*/
return null;
}
What changes can I make to my LDAP authentication method so that I can get the correct password and name values checked there?
I'm trying to authenticate a set of credentials against an LDAP server and I was able to authenticate them successfully. Now am trying to get the full name or the display name of the user logged-in into the server. Am unable to get the same. Being new to LDAP concepts, am unable to figure out a way to get the full display name of the user. Can some please help me how to get the full display name of the user logged in.
Below is the shiro.ini file am using:
[main]
activeDirectoryRealm =
org.apache.shiro.realm.activedirectory.ActiveDirectoryRealm
activeDirectoryRealm.systemUsername = adminusername
activeDirectoryRealm.systemPassword = adminpswd
activeDirectoryRealm.searchBase = "OU=User Accounts,DC=dmn,DC=net"
activeDirectoryRealm.url = ldaps://localhost:389
My Java code is as below:
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
public class ExampleActiveDirectory {
public static final String userName = "myusername";
public static final String password = "mypassword";
public static void main(String[] args)
{
//Factory<SecurityManager> factory = new IniSecurityManagerFactory("N:\\workspace\\LdapAuthentication\\src\\auth.ini");
Factory<SecurityManager> factory = new IniSecurityManagerFactory("N:\\workspace\\LdapAuthentication\\src\\shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager( securityManager );
System.out.println( "userName is : " +userName);
System.out.println( "password is : " +password);
UsernamePasswordToken token = new UsernamePasswordToken( userName,password );
Subject currentUser = SecurityUtils.getSubject();
try
{
//currentUser.login( token ) ;
securityManager.login(currentUser,token).isAuthenticated();
System.out.println( "We've authenticated! :)" );
}
catch ( AuthenticationException e )
{
System.out.println( "We did not authenticate :(" );
e.printStackTrace();
}
}
}
Thanks for the info.
link - http://www.deepakgaikwad.net/index.php/2009/09/24/retrieve-basic-user-attributes-from-active-directory-using-ldap-in-java.html
Found a solution as below:
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import org.apache.shiro.web.tags.UserTag;
public class RetrieveUserAttributes {
public static void main(String[] args) {
RetrieveUserAttributes retrieveUserAttributes = new RetrieveUserAttributes();
retrieveUserAttributes.getUserBasicAttributes("username", retrieveUserAttributes.getLdapContext());
}
public LdapContext getLdapContext(){
LdapContext ctx = null;
try{
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "Simple");
env.put(Context.SECURITY_PRINCIPAL, "adminusername");
env.put(Context.SECURITY_CREDENTIALS, "adminpswrd");
env.put(Context.PROVIDER_URL, "ldaps://localhost:389");
ctx = new InitialLdapContext(env, null);
System.out.println("Connection Successful.");
}catch(NamingException nex){
System.out.println("LDAP Connection: FAILED");
nex.printStackTrace();
}
return ctx;
}
UserTag getUserBasicAttributes(String username, LdapContext ctx) {
UserTag user=null;
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
String[] attrIDs = { "distinguishedName",
"sn",
"givenname",
"mail",
"telephonenumber"};
constraints.setReturningAttributes(attrIDs);
//First input parameter is search bas, it can be "CN=Users,DC=YourDomain,DC=com"
//Second Attribute can be uid=username
NamingEnumeration answer = ctx.search("DC=domain,DC=com", "sAMAccountName="
+ "username", constraints);
if (answer.hasMore()) {
Attributes attrs = ((SearchResult) answer.next()).getAttributes();
System.out.println("distinguishedName "+ attrs.get("distinguishedName"));
System.out.println("givenname "+ attrs.get("givenname"));
System.out.println("sn "+ attrs.get("sn"));
System.out.println("mail "+ attrs.get("mail"));
System.out.println("telephonenumber "+ attrs.get("telephonenumber"));
}else{
throw new Exception("Invalid User");
}
} catch (Exception ex) {
ex.printStackTrace();
}
return user;
}
}
I used apacheds(as LDAP server) and inserted entries into it using apache directory studio. For the userPassword atribute I selected plain text only. but, apache directory studio is encrypting it. i don't know why is that. Now, my java program to retrieve that entry is giving me a ssha encrypted password. can anyone out there help me in how to decode it ?
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
class GetAttrs {
public static void main(String[] args) {
// Set up the environment for creating the initial context
Hashtable<String, Object> env = new Hashtable<String, Object>(11);
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:10389/o=mojo");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
env.put(Context.SECURITY_CREDENTIALS, "secret");
try {
// Create initial context
DirContext ctx = new InitialDirContext(env);
// Specify the ids of the attributes to return
String[] attrIDs = { "cn", "sn", "uid", "userPassword" };
// Get the attributes requested
Attributes answer = ctx
.getAttributes("cn=Harish Koppala, ou=Users", attrIDs);
// Print the answer
printAttrs(answer);
// Close the context when we're done
ctx.close();
} catch (Exception e) {
e.printStackTrace();
}
}
static void printAttrs(Attributes attrs) throws Exception{
if (attrs == null) {
System.out.println("No attributes");
} else {
/* Print each attribute */
try {
for (NamingEnumeration ae = attrs.getAll(); ae.hasMore();) {
Attribute attr = (Attribute) ae.next();
System.out.print(attr.getID()+" : ");
/* print each value */
if("userpassword".equalsIgnoreCase(attr.getID())){
for (
NamingEnumeration e = attr.getAll();
e.hasMore();
System.out.println(new String((byte[])e.next()))
);
}else{
for (
NamingEnumeration e = attr.getAll();
e.hasMore();
System.out.println(e.next())
);
}
}
} catch (NamingException e) {
e.printStackTrace();
}
}
}
}
output:
userPassword : {SSHA}SKA8QY7BBX0tgdZlzL+3sEDFnIBsJwd8VHjexw==
uid : hwilliams
sn : Williams
cn : Hugo Williams
It isn't encrypting it. It is securely hashing it. You can't decrypt or decode it.
I have successfully used the code below to authenticate users in an LDAP environment for a number of years. Now, I have a client who wants me to log into to the LDAP directory (it's an Active Directory LDAP environment) prior to authentication and then do the authentication. In other words, I would pass two sets of credentials to the server, one to gain access to the LDAP directory, and the second to actually do the authentication. Is there an easy way to modify my existing code to do this? Are their alternative code patterns that would allow this to be done easily?
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
public class ADAuthenticator {
private String domain;
private String ldapHost;
private String searchBase;
public ADAuthenticator()
{
this.domain = "<your domain>";
this.ldapHost = "ldap://<your AD controller>";
this.searchBase = "your AD root e.g. dc=abbl,dc=org";
}
public ADAuthenticator(String domain, String host, String dn)
{
this.domain = domain;
this.ldapHost = host;
this.searchBase = dn;
}
public Map authenticate(String user, String pass)
{
String returnedAtts[] ={ "sn", "givenName", "mail" };
String searchFilter = "(&(objectClass=user)(sAMAccountName=" + user + "))";
//Create the search controls
SearchControls searchCtls = new SearchControls();
searchCtls.setReturningAttributes(returnedAtts);
//Specify the search scope
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapHost);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, user + "#" + domain);
env.put(Context.SECURITY_CREDENTIALS, pass);
LdapContext ctxGC = null;
try
{
ctxGC = new InitialLdapContext(env, null);
//Search objects in GC using filters
NamingEnumeration answer = ctxGC.search(searchBase, searchFilter, searchCtls);
while (answer.hasMoreElements())
{
SearchResult sr = (SearchResult) answer.next();
Attributes attrs = sr.getAttributes();
Map amap = null;
if (attrs != null)
{
amap = new HashMap();
NamingEnumeration ne = attrs.getAll();
while (ne.hasMore())
{
Attribute attr = (Attribute) ne.next();
amap.put(attr.getID(), attr.get());
}
ne.close();
}
return amap;
}
}
catch (NamingException ex)
{
ex.printStackTrace();
}
return null;
}
}
I have this error when I run my Java program. The thing that I want to do is to be able to create an LDAP user with Java code. My goal is to be able to add, remove, set password and add the user in an existing group.
The better thing is to have an input box also
Thanks
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.naming.NamingException;
import java.util.Hashtable;
import java.util.Properties;
public class LdapExampleAdd {
private static LdapContext ctx;
public static void main(String[] args)
{
//Identify service provider to use
Hashtable env = new Hashtable();
Properties prop = new Properties();
prop.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
prop.put("java.naming.provider.url", "ldap://ldapserverip:389");
prop.put("java.naming.security.principal", "cn=Administrator,cn=Users,dc=domain,dc=local");
prop.put("java.naming.security.credentials", "password");
try {
setCtx(new InitialLdapContext(prop, null));
System.out.println("Connected");
}
catch (NamingException ex) {
System.err.println("Not connected");
System.exit(0);
}
try
{
// Create the initial directory context
InitialDirContext initialContext = new InitialDirContext(env);
DirContext dCtx = (DirContext)initialContext;
Attributes matchAttrs = new BasicAttributes(true);
matchAttrs.put(new BasicAttribute("uid", "defaultuser"));
matchAttrs.put(new BasicAttribute("cn", "defaultuser"));
matchAttrs.put(new BasicAttribute("givenname", "defaultuser"));
matchAttrs.put(new BasicAttribute("sn", "defaultuser"));
matchAttrs.put(new BasicAttribute("userpassword", "password"));
matchAttrs.put(new BasicAttribute("objectclass", "top"));
matchAttrs.put(new BasicAttribute("objectclass", "person"));
matchAttrs.put(new BasicAttribute("objectclass", "organizationalPerson"));
matchAttrs.put(new BasicAttribute("objectclass","inetorgperson"));
String name="uid=defaultuser";
InitialDirContext iniDirContext = (InitialDirContext)dCtx;
iniDirContext.bind(name,dCtx,matchAttrs);
iniDirContext.close();
dCtx.close();
}
catch (NamingException ne)
{
System.err.println(ne);
}
catch(Exception e)
{
System.err.println(e);
}
}
public static LdapContext getCtx() {
return ctx;
}
public static void setCtx(LdapContext ctx) {
LdapExampleAdd.ctx = ctx;
}
}
Who will be the real expert
You create the InitialLdapContext, but never use it. You create the HashTable, but never populate it.