I'm newer coding ldap using spring-boot (ldapTemplate). I want to get the groups that a user belongs, get the list of membreOf attributes, I tried this:
#Override
public Person getUserInfo(String uid, String orgnisationUnit) throws InvalidNameException {
Name dn = bindDn(uid, orgnisationUnit);
return (Person ) ldapTemplate.lookup(dn, new LdapMapper());
}
This is myLdapMapper:
public class LdapMapper implements ContextMapper<Object> {
#Override
public Object mapFromContext(Object ctx) {
DirContextAdapter context = (DirContextAdapter) ctx;
Person p = new Person();
p.setFirstName(context.getStringAttribute("cn"));
p.setMailAddress(context.getStringAttribute("uid"));
p.setRoles(context.getObjectAttributes("memberOf")); // roles was declared like: private Object[] roles
return p;
}
}
Would you have any propositions ?
import java.io.*;
import java.text.*;
import java.util.*;
import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.ldap.InitialLdapContext;
import javax.xml.bind.*;
public class LdapConnection {
public void getUserDetail(String user_name, String passwd) throws NamingException {
DirContext ctx = null;
String username = user_name;
try {
ctx = context(user_name, passwd);
SearchControls searchCtls = new SearchControls();
String returnedAtts[] = {"sn", "mail", "cn", "givenName",
"telephoneNumber", "manager","memberOf"};
searchCtls.setReturningAttributes(returnedAtts);
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String searchFilter = "(&(objectClass=user)(mail=*))";
String searchBase = "OU=India,DC=<Domain Component>";
NamingEnumeration<?> answer = ctx.search(searchBase, searchFilter,
searchCtls);
while (answer.hasMoreElements()) {
SearchResult sr = (SearchResult) answer.next();
Attributes attrs = sr.getAttributes();
if (attrs != null) {
try {
String cn = attrs.get("cn").get().toString();
String mail_id = attrs.get("mail").get().toString();
NamingEnumeration<?> memberOf = attrs.get("memberOf").getAll();
while (answer.hasMoreElements()) {
String member =(String)memberOf.next();
System.out.println("memberOf : " + member);
}
} catch (NullPointerException e) {
System.out.println(e.getMessage());
}
}
}
} catch (NamingException e) {
System.out.println(e.getMessage());
} finally {
if(!ctx.equals(null))
ctx.close(); }
}
/**
* This method will return Directory Context to the Called method,Used to
* bind with LDAP
*/
public DirContext context(String user, String passwd)
throws NamingException {
Hashtable<String, String> env = new Hashtable<String, String>();
String adminName = "CN=" + user
+ ",OU=User,OU=India,DC=<Domain Component>";
String adminPassword = passwd;
String ldapURL = <ldapserver url with port>;
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapURL);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, adminName);
env.put(Context.SECURITY_CREDENTIALS, adminPassword);
DirContext ctx = new InitialLdapContext(env, null);
return ctx; }
public static void main(String[] args) throws NamingException {
LdapConnection ldap = new LdapConnection();
ldap.getUserDetail("username","password");
}
}`
I hope this code will solve you problem.
Related
Is their any way to fetch duplicates from AD using java ? I see we can do it in power shell by grouping all usernames and then checking count >1.
https://gallery.technet.microsoft.com/scriptcenter/Find-Active-Directory-c8789b42
Please help :).
you should get all objects of a special type(such as user, group , ...) and their attributes. then check duplicate attributes of all objects. for do this, you can insert each attributes in a hasp map as a key, and insert all value of attribute per each object and check is duplicated or not ?
use JAVA JNDI to access AD server as follow:
/**
* retrieve all attributes of a named object.
*
*/
class GetAllAttrs {
static void printAttrs(Attributes attrs) {
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.println("attribute: " + attr.getID());
/* print each value */
for (NamingEnumeration e = attr.getAll(); e.hasMore(); System.out
.println("value: " + e.next()))
;
}
} catch (NamingException e) {
e.printStackTrace();
}
}
}
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:389/o=JNDITutorial");
try {
// Create the initial context
DirContext ctx = new InitialDirContext(env);
// Get all the attributes of named object
Attributes answer = ctx.getAttributes("cn=Ted Geisel, ou=People");
// Print the answer
printAttrs(answer);
// Close the context when we're done
ctx.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
also you can use search filter to limit your outputs:
public class LdapSearch {
public static void main(String[] args) throws Exception {
Hashtable env = new Hashtable();
String sp = "com.sun.jndi.ldap.LdapCtxFactory";
env.put(Context.INITIAL_CONTEXT_FACTORY, sp);
String ldapUrl = "ldap://localhost:389/dc=yourName, dc=com";
env.put(Context.PROVIDER_URL, ldapUrl);
DirContext dctx = new InitialDirContext(env);
String base = "ou=People";
SearchControls sc = new SearchControls();
String[] attributeFilter = { "cn", "mail" };
sc.setReturningAttributes(attributeFilter);
sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
String filter = "(&(sn=W*)(l=Criteria*))";
NamingEnumeration results = dctx.search(base, filter, sc);
while (results.hasMore()) {
SearchResult sr = (SearchResult) results.next();
Attributes attrs = sr.getAttributes();
Attribute attr = attrs.get("cn");
System.out.print(attr.get() + ": ");
attr = attrs.get("mail");
System.out.println(attr.get());
}
dctx.close();
}
}
I wrote the code on Ubuntu 16 and tried to connect to ActiveDirectory on a Windows Server 2012 virtual machine.
The user name is : siwar
The user password is : siwarmp
The domain name is: squeezer.celtron.com
The VM host address (Windows server 2012) : 192.168.1.115
The following code did not work and generated an Authentification:
package ldap;
import java.util.Hashtable;
import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.SizeLimitExceededException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
public class LdapMain {
static DirContext ctx = null;
static String userLog = "cn=siwar,ou=users,dc=squeezer,dc=celtron,dc=com";
// static String userLog =
// "cn=siwar,cn=users,dc=squeezer,dc=celtron,dc=com";
static String userMP = "siwarmp";
public static void main(String args[]) throws Exception {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://192.168.1.115:389/");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=squeezer,dc=celtron,dc=com");
env.put(Context.SECURITY_CREDENTIALS, "ldap");
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
getGroup(env, 500);
getRole(env, "readonly");
validateLogin(env, userLog, userMP);
}
private static SearchControls getSimpleSearchControls() {
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setTimeLimit(30000);
// String[] attrIDs = {"objectGUID"};
// searchControls.setReturningAttributes(attrIDs);
return searchControls;
}
public static Boolean validateLogin(Hashtable<String, String> env, String userName, String userPassword) {
NamingEnumeration<SearchResult> results = null;
try {
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setCountLimit(1);
controls.setTimeLimit(5000);
env.put(Context.SECURITY_PRINCIPAL, userName);
env.put(Context.SECURITY_CREDENTIALS, userPassword);
ctx = new InitialDirContext(env);
results = ctx.search("ou=users,dc=celtron,dc=com", "(objectclass=inetOrgPerson)",
getSimpleSearchControls());
// results = ctx.search("dc=celtron,dc=com",
// "(objectclass=inetOrgPerson)", getSimpleSearchControls());
results = ctx.search(userName, "(objectclass=*)", getSimpleSearchControls());
System.out.println(results);
while (results.hasMore()) {
SearchResult result = (SearchResult) results.next();
Attributes attrs = result.getAttributes();
Attribute dnAttr = attrs.get("cn");
String dn = (String) dnAttr.get();
System.out.println(dn);
Attribute gidAttr = attrs.get("gidNumber");
String gid = (String) gidAttr.get();
System.out.println(gid);
// User Exists, Validate the Password
env.put(Context.SECURITY_PRINCIPAL, userName);
env.put(Context.SECURITY_CREDENTIALS, userPassword);
return true;
}
return false;
} catch (AuthenticationException e) { // Invalid Login
return false;
} catch (NameNotFoundException e) { // The base context was not found.
return false;
} catch (SizeLimitExceededException e) {
throw new RuntimeException("LDAP Query Limit Exceeded, adjust the query to bring back less records", e);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
try {
if (results != null) {
results.close();
}
if (ctx != null) {
ctx.close();
}
} catch (Exception e) { /* Do Nothing */
}
}
}
public static Boolean getRole(Hashtable<String, String> env, String roleName) {
NamingEnumeration<SearchResult> results = null;
try {
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setCountLimit(1);
controls.setTimeLimit(5000);
ctx = new InitialDirContext(env);
results = ctx.search("cn=readonly,ou=roles,dc=celtron,dc=com", "(objectclass=organizationalRole)",
getSimpleSearchControls());
while (results.hasMore()) {
SearchResult result = (SearchResult) results.next();
Attributes attrs = result.getAttributes();
Attribute dnAttr = attrs.get("roleOccupant");
String dn = (String) dnAttr.get();
System.out.println(dn);
return true;
}
return false;
} catch (AuthenticationException e) { // Invalid Login
System.out.println("Auth failed");
return false;
} catch (NameNotFoundException e) { // The base context was not found.
return false;
} catch (SizeLimitExceededException e) {
throw new RuntimeException("LDAP Query Limit Exceeded, adjust the query to bring back less records", e);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
try {
if (results != null) {
results.close();
}
if (ctx != null) {
ctx.close();
}
} catch (Exception e) {
}
}
}
public static String getGroup(Hashtable<String, String> env, int gid) {
NamingEnumeration<SearchResult> results = null;
try {
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setCountLimit(1);
controls.setTimeLimit(5000);
ctx = new InitialDirContext(env);
results = ctx.search("ou=groups,dc=celtron,dc=com", "(gidNumber=500)", getSimpleSearchControls());
while (results.hasMore()) {
SearchResult result = (SearchResult) results.next();
Attributes attrs = result.getAttributes();
Attribute dnAttr = attrs.get("cn");
String dn = (String) dnAttr.get();
System.out.println(dn);
return dn;
}
return "";
} catch (AuthenticationException e) {
return "";
} catch (NameNotFoundException e) {
return "";
} catch (SizeLimitExceededException e) {
throw new RuntimeException("LDAP Query Limit Exceeded, adjust the query to bring back less records", e);
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
try {
if (results != null) {
results.close();
}
if (ctx != null) {
ctx.close();
}
} catch (Exception e) {
}
}
}
}
We have configured OID/OAM as our security providers in weblogic security.
On checking user attributes, only user id is visible.
How to get all attributes available in OID/OAM to available in Weblogic Security User and Groups?
Short Version: Use JMX as described here to get the configured OID-Authenticator-MBean. You can then use that MBean to get the necessary parameters to establish your own Connection to the OID and traverse the attributes. You might also want to read about Java Naming and Directory Operations here
Sample Implementation:
package test;
import java.util.Hashtable;
import javax.management.Descriptor;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.modelmbean.ModelMBeanInfo;
import javax.naming.Context;
import javax.naming.InitialContext;
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;
import javax.naming.directory.SearchControls;
public class OIDFromWLBean {
// The attribute you want to read (for a specific user)
private static final String ATTRIBUTE_NAME = "pwdChangedTime";
// The Class of the configured Authenticator Provider, here it is OID
// Check the API if you use something else
// API Docs:
// http://docs.oracle.com/cd/E12839_01/apirefs.1111/e13945/weblogic/security/providers/authentication/OracleInternetDirectoryAuthenticatorMBean.html
final String OID_AUTHENTICATOR_MBEAN_NAME = "weblogic.security.providers.authentication.OracleInternetDirectoryAuthenticatorMBean";
// The rest here should be static and stay unchanged
private static final String COM_SUN_JNDI_LDAP_LDAP_CTX_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
private static final String INTERFACE_CLASS_NAME = "interfaceClassName";
private static final String AUTHENTICATION_PROVIDERS = "AuthenticationProviders";
private static final String DEFAULT_REALM = "DefaultRealm";
private static final String SECURITY_CONFIGURATION = "SecurityConfiguration";
private static final String DOMAIN_CONFIGURATION = "DomainConfiguration";
final String MBEAN_SERVER = "java:comp/env/jmx/domainRuntime";
final String DOMAIN_MBEAN_NAME = "com.bea:Name=DomainRuntimeService,Type=weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean";
public String getAttribute(String username, String password) {
final MBeanServer connection = getConnection();
final ObjectName defaultAuthenticator = getAuthenticator(connection);
String rest = null;
try {
String host = getHost(defaultAuthenticator, connection);
String port = getPort(defaultAuthenticator, connection);
String userBaseDN = getUserBaseDN(defaultAuthenticator, connection);
DirContext ctx = getConnectionLdapOid(username, password, host, port, userBaseDN);
rest = getAttribute(ctx, "cn=" + username + "," + userBaseDN, username);
} catch (Exception ref) {
// Do something to handle that
}
return rest;
}
private MBeanServer getConnection() {
MBeanServer connection;
try {
InitialContext ctx = new InitialContext();
connection = (MBeanServer) ctx.lookup(MBEAN_SERVER);
} catch (Exception e) {
throw new RuntimeException(e);
}
return connection;
}
private ObjectName getAuthenticator(MBeanServer connection) {
ObjectName authenticator = null;
ObjectName[] authenticationProviders;
try {
ObjectName configurationMBeans = new ObjectName(DOMAIN_MBEAN_NAME);
ObjectName domain = (ObjectName) connection.getAttribute(configurationMBeans, DOMAIN_CONFIGURATION);
ObjectName security = (ObjectName) connection.getAttribute(domain, SECURITY_CONFIGURATION);
ObjectName realm = (ObjectName) connection.getAttribute(security, DEFAULT_REALM);
authenticationProviders = (ObjectName[]) connection.getAttribute(realm, AUTHENTICATION_PROVIDERS);
for (int p = 0; p < authenticationProviders.length; p++) {
ModelMBeanInfo info = (ModelMBeanInfo) connection.getMBeanInfo(authenticationProviders[p]);
Descriptor desc = info.getMBeanDescriptor();
String className = (String) desc.getFieldValue(INTERFACE_CLASS_NAME);
if (className.equals(OID_AUTHENTICATOR_MBEAN_NAME)) {
authenticator = authenticationProviders[p];
break;
}
}
} catch (Exception e) {
// Do something to handle that
}
return authenticator;
}
private DirContext getConnectionLdapOid(String username, String password, String host, String port, String userBaseDN) throws NamingException {
Hashtable<String, String> jndiProps = new Hashtable<String, String>();
jndiProps.put(Context.INITIAL_CONTEXT_FACTORY, COM_SUN_JNDI_LDAP_LDAP_CTX_FACTORY);
jndiProps.put(Context.PROVIDER_URL, "ldap://" + host + ":" + port);
jndiProps.put(Context.SECURITY_AUTHENTICATION, "simple");
jndiProps.put(Context.SECURITY_PRINCIPAL, "cn=" + username + "," + userBaseDN);
jndiProps.put(Context.SECURITY_CREDENTIALS, password);
DirContext ctx = new InitialDirContext(jndiProps);
return ctx;
}
private String getHost(ObjectName defaultAuthenticator, MBeanServer connection) throws Exception {
String result = (String) connection.getAttribute(defaultAuthenticator, "Host");
return result;
}
private String getPort(ObjectName defaultAuthenticator, MBeanServer connection) throws Exception {
String result = ((Integer) connection.getAttribute(defaultAuthenticator, "Port")).toString();
return result;
}
private String getUserBaseDN(ObjectName defaultAuthenticator, MBeanServer connection) throws Exception {
String result = (String) connection.getAttribute(defaultAuthenticator, "UserBaseDN");
return result;
}
#SuppressWarnings("rawtypes")
public static String getAttribute(DirContext ctx, String DN, String user) {
String attrName, attrValue = "";
String result = null;
try {
SearchControls ctls = new SearchControls();
ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
ctls.setReturningAttributes(new String[0]);
NamingEnumeration sre = null;
sre = ctx.search(DN, "cn=" + user, ctls);
if (!(sre != null && sre.hasMoreElements())) {
return null;
}
Attributes attrs = null;
String returnAttrs[] = { ATTRIBUTE_NAME };
attrs = ctx.getAttributes(DN, returnAttrs);
NamingEnumeration enu = attrs.getAll();
if ((enu != null) && enu.hasMore()) {
Attribute attr = (Attribute) enu.next();
attrName = attr.getID();
NamingEnumeration attrValues = attr.getAll();
if (attrValues.hasMore()) {
attrValue = (String) attrValues.next();
}
}
result = attrValue;
} catch (NamingException e) {
// Do something to handle that
}
return result;
}
}
I'm trying to change the mail and password attributes of Active Directory using java. To do this, it was generated a security certificate and imported into the certificate store of the jvm (carcerts). The connection is made using ssl successfully however when trying to change any field, eg mail,I get the following error message:
javax.naming.OperationNotSupportedException: [LDAP: error code 53 - 00002035: LdapErr: DSID-0C090B3E, comment: Operation not allowed through GC port, data 0, v1db1
source code:
// change mail
private void salvarEmailESenhaNoAd() throws IOException, NamingException {
Properties mudaSenhaProperties = new PropertiesFactory().propertiesByJndi("mudaSenha");
ADUtil adUtil = null;
try
{
adUtil = new ADUtil(mudaSenhaProperties);
adUtil.changeEmail("CN=018061671627,OU=SDS,OU=CS,OU=STI,OU=DG,OU=PRES,OU=TRERN,DC=tre-rn,DC=jus,DC=br", dadosUsuario.getEmail());
}
finally
{
if (adUtil != null)
{
adUtil.close();
}
}
}
public class ADUtil {
private LdapContext ldapContext = null;
public ADUtil(Properties properties) throws NamingException
{
ldapContext = createUserContext(properties);
}
private LdapContext createUserContext(Properties properties) throws NamingException {
String javaNamingFactoryInitial = properties.getProperty("java.naming.factory.initial");
String javaNamingProviderUrl = properties.getProperty("java.naming.provider.url");
String javaNamingSecurityAuthentication = properties.getProperty("java.naming.security.authentication");
String javaNamingSecurityPrincipal = properties.getProperty("java.naming.security.principal");
String javaNamingSecurityCredentials = properties.getProperty("java.naming.security.credentials");
String javaNamingSecurityProtocol = properties.getProperty("java.naming.security.protocol");
String javaNamingReferral = properties.getProperty("java.naming.referral");
String javaNetSslTrustStore = properties.getProperty("javax.net.ssl.trustStore");
String javaNetSslTrustStorePassword = properties.getProperty("javax.net.ssl.trustStorePassword");
Hashtable<String, String> env = new Hashtable<String, String>();
System.setProperty("javax.net.ssl.trustStore", javaNetSslTrustStore);
System.setProperty("javax.net.ssl.trustStorePassword", javaNetSslTrustStorePassword);
env.put(Context.INITIAL_CONTEXT_FACTORY, javaNamingFactoryInitial);
env.put(Context.SECURITY_AUTHENTICATION, javaNamingSecurityAuthentication);
env.put(Context.SECURITY_PRINCIPAL, javaNamingSecurityPrincipal);
env.put(Context.SECURITY_CREDENTIALS, javaNamingSecurityCredentials);
env.put(Context.SECURITY_PROTOCOL, javaNamingSecurityProtocol); // para poder modificar password y grupos del usuario.
env.put(Context.PROVIDER_URL, javaNamingProviderUrl);
env.put(Context.REFERRAL, javaNamingReferral);
return new InitialLdapContext(env, null);
}
public void changePassword(String userCN, String newPassword) throws NamingException, UnsupportedEncodingException, IOException {
modifyAdAttribute(userCN, "unicodePwd", converteString(newPassword));
System.out.println("Password changed for " + userCN);
}
public void changeEmail(String userDN, String newEmail) throws NamingException, UnsupportedEncodingException, IOException {
modifyAdAttribute(userDN, "mail", converteString(newEmail));
System.out.println("Email changed for " + newEmail);
}
private void modifyAdAttribute(String userCN, String attribute, Object value) throws NamingException{
ModificationItem[] modificationItem = new ModificationItem[1];
modificationItem[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute(attribute, value));
ldapContext.modifyAttributes(userCN, modificationItem);
}
private static byte[] converteString(String password) throws UnsupportedEncodingException{
String newQuotedPassword = "\"" + password + "\"";
return newQuotedPassword.getBytes("UTF-16LE");
}
public void close() throws NamingException
{
if (ldapContext != null)
{
ldapContext.close();
}
}
Reading the attributes is usually done with the code below:
public class TesteLdap {
/**
* #param args the command line arguments
*/
private static SearchControls getSimpleSearchControls() {
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setTimeLimit(30000);
//String[] attrIDs = {"objectGUID"};
//searchControls.setReturningAttributes(attrIDs);
return searchControls;
}
public static void main(String[] args) throws NamingException {
try {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://rndc10.tre-rn.jus.br:3269");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "user");
env.put(Context.SECURITY_CREDENTIALS, "password");
env.put(Context.SECURITY_PROTOCOL, "ssl");
env.put(Context.REFERRAL, "ignore");
String filter = "(&(objectClass=user)(CN=018061671627))";
LdapContext ctx = new InitialLdapContext(env, null);
ctx.setRequestControls(null);
NamingEnumeration<?> namingEnum = ctx.search("OU=DG,OU=PRES,OU=TRERN,DC=tre-rn,DC=jus,DC=br", filter, getSimpleSearchControls());
while (namingEnum.hasMore()) {
SearchResult result = (SearchResult) namingEnum.next();
Attributes attrs = result.getAttributes();
System.out.println(attrs.get("cn"));
System.out.println(attrs.get("displayname"));
System.out.println(attrs.get("mail"));
System.out.println(attrs.get("distinguishedName"));
}
namingEnum.close();
} catch (Exception e) {
e.printStackTrace();
My environment: Active Directory on Windows 2008R2 Standart, Open JDK 7 running on unbutu 12.10.
I would be grateful if someone help me because I've tried everything but I can not make it work.
The error seems to be self-explanatory. You should perform this operation over LDAPS using port 636.
Have you tried to use
env.put(Context.PROVIDER_URL, "ldaps://rndc10.tre-rn.jus.br:636");
(Note that ldaps:// is not mandatory if you specify ssl separately).
Do you have RODCs (Read only DCs) in your environment? And if so, is rndc10.tre-rn.jus.br a RODC?
Perhaps you should be pointing to a DC that is writeable?
Have you tried updating this string:
env.put(Context.PROVIDER_URL, "ldap://rndc10.tre-rn.jus.br:3269");
to:
env.put(Context.PROVIDER_URL, "ldaps://rndc10.tre-rn.jus.br:3269");
^
I have tried all the things to connect Facebook with XMPP but i have faced only
one error all the time which is :
SASL authentication failed using mechanism DIGEST-MD5 I am implementing following method to perform this task :
public class MySASLDigestMD5Mechanism extends SASLMechanism {
public MySASLDigestMD5Mechanism(SASLAuthentication saslAuthentication) {
super(saslAuthentication);
}
protected void authenticate() throws IOException, XMPPException {
String[] mechanisms = { getName() };
Map<String, String> props = new HashMap<String, String>();
sc = Sasl.createSaslClient(mechanisms, null, "xmpp", hostname, props, this);
super.authenticate();
}
public void authenticate(String username, String host, String password) throws IOException, XMPPException {
this.authenticationId = username;
this.password = password;
this.hostname = host;
String[] mechanisms = { getName() };
Map<String,String> props = new HashMap<String,String>();
sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props, this);
super.authenticate();
}
public void authenticate(String username, String host, CallbackHandler cbh) throws IOException, XMPPException {
String[] mechanisms = { getName() };
Map<String,String> props = new HashMap<String,String>();
sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props, (org.apache.harmony.javax.security.auth.callback.CallbackHandler) cbh);
super.authenticate();
}
protected String getName() {
return "DIGEST-MD5";
}
/*public void challengeReceived1(String challenge) throws IOException {
// Build the challenge response stanza encoding the response text
StringBuilder stanza = new StringBuilder();
byte response[];
if (challenge != null) {
response = sc.evaluateChallenge(Base64.decode(challenge));
} else {
response = sc.evaluateChallenge(null);
}
String authenticationText="";
if (response != null) { // fix from 3.1.1
authenticationText = Base64.encodeBytes(response, Base64.DONT_BREAK_LINES);
if (authenticationText.equals("")) {
authenticationText = "=";
}
}
stanza.append("<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
stanza.append(authenticationText);
stanza.append("</response>");
// Send the authentication to the server
getSASLAuthentication().send(stanza.toString());
}*/
public void challengeReceived(String challenge)
throws IOException {
byte response[];
if (challenge != null) {
response = sc.evaluateChallenge(Base64.decode(challenge));
} else {
response = sc.evaluateChallenge(new byte[0]);
}
Packet responseStanza;
if (response == null) {
responseStanza = new Response();
} else {
responseStanza = new Response(Base64.encodeBytes(response, Base64.DONT_BREAK_LINES));
}
getSASLAuthentication().send(responseStanza);
}
}
And Connection Function is :
try{
SASLAuthentication.registerSASLMechanism("DIGEST-MD5",MySASLDigestMD5Mechanism. class);
ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com",5222);
config.setSASLAuthenticationEnabled(true);
config.setRosterLoadedAtLogin (true);
connection = new XMPPConnection(config);
connection.connect();
Log.d("Connect...", "Afetr Connect");
connection.login("username#chat.facebook.com", "password");
Log.d("done","XMPP client logged in");
}
catch(XMPPException ex)
{
Log.d("not done","in catchhhhhhhhh");
System.out.println(ex.getMessage ());
connection.disconnect();
}
}
but "After connect" it gone to the ctach and give me error like :
SASL authentication failed using mechanism DIGEST-MD5
I searched all blog and find same thing but i dont know what am i doing wrong here..
If is there any other way or solution to connect Facebook XMPP then please Help me
ASAP
Finally, thanks to the no.good.at.coding code and the suggestion of harism, I've been able to connect to the Facebook chat. This code is the Mechanism for the Asmack library (the Smack port for Android). For the Smack library is necessary to use the no.good.at.coding mechanism.
SASLXFacebookPlatformMechanism.java:
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import org.apache.harmony.javax.security.auth.callback.CallbackHandler;
import org.apache.harmony.javax.security.sasl.Sasl;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.sasl.SASLMechanism;
import org.jivesoftware.smack.util.Base64;
public class SASLXFacebookPlatformMechanism extends SASLMechanism
{
private static final String NAME = "X-FACEBOOK-PLATFORM";
private String apiKey = "";
private String applicationSecret = "";
private String sessionKey = "";
/** * Constructor. */
public SASLXFacebookPlatformMechanism(SASLAuthentication saslAuthentication)
{
super(saslAuthentication);
}
#Override
protected void authenticate() throws IOException, XMPPException
{
getSASLAuthentication().send(new AuthMechanism(NAME, ""));
}
#Override
public void authenticate(String apiKeyAndSessionKey, String host, String applicationSecret) throws IOException, XMPPException
{
if (apiKeyAndSessionKey == null || applicationSecret == null)
{
throw new IllegalArgumentException("Invalid parameters");
}
String[] keyArray = apiKeyAndSessionKey.split("\\|", 2);
if (keyArray.length < 2)
{
throw new IllegalArgumentException( "API key or session key is not present"); }
this.apiKey = keyArray[0];
this.applicationSecret = applicationSecret;
this.sessionKey = keyArray[1];
this.authenticationId = sessionKey;
this.password = applicationSecret;
this.hostname = host;
String[] mechanisms = { "DIGEST-MD5" };
Map<String, String> props = new HashMap<String, String>();
this.sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props,this);
authenticate();
}
#Override
public void authenticate(String username, String host, CallbackHandler cbh)throws IOException, XMPPException
{
String[] mechanisms = { "DIGEST-MD5" };
Map<String, String> props = new HashMap<String, String>();
this.sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props,cbh);
authenticate();
} #Override protected String getName()
{
return NAME;
}
#Override
public void challengeReceived(String challenge) throws IOException
{
byte[] response = null;
if (challenge != null)
{
String decodedChallenge = new String(Base64.decode(challenge));
Map<String, String> parameters = getQueryMap(decodedChallenge);
String version = "1.0";
String nonce = parameters.get("nonce");
String method = parameters.get("method");
long callId = new GregorianCalendar().getTimeInMillis();
String sig = "api_key=" + apiKey + "call_id=" + callId + "method=" + method + "nonce=" + nonce + "session_key=" + sessionKey + "v=" + version + applicationSecret;
try
{
sig = md5(sig);
}
catch (NoSuchAlgorithmException e)
{
throw new IllegalStateException(e);
}
String composedResponse = "api_key=" + URLEncoder.encode(apiKey, "utf-8") + "&call_id=" + callId + "&method="+ URLEncoder.encode(method, "utf-8") + "&nonce="+ URLEncoder.encode(nonce, "utf-8")+ "&session_key="+ URLEncoder.encode(sessionKey, "utf-8") + "&v="+ URLEncoder.encode(version, "utf-8") + "&sig="+ URLEncoder.encode(sig, "utf-8");response = composedResponse.getBytes("utf-8");
}
String authenticationText = "";
if (response != null)
{
authenticationText = Base64.encodeBytes(response, Base64.DONT_BREAK_LINES);
}
// Send the authentication to the server
getSASLAuthentication().send(new Response(authenticationText));
}
private Map<String, String> getQueryMap(String query)
{
Map<String, String> map = new HashMap<String, String>();
String[] params = query.split("\\&");
for (String param : params)
{
String[] fields = param.split("=", 2);
map.put(fields[0], (fields.length > 1 ? fields[1] : null));
}
return map;
}
private String md5(String text) throws NoSuchAlgorithmException,UnsupportedEncodingException
{
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(text.getBytes("utf-8"), 0, text.length());
return convertToHex(md.digest());
}
private String convertToHex(byte[] data)
{
StringBuilder buf = new StringBuilder();
int len = data.length;
for (int i = 0; i < len; i++)
{
int halfByte = (data[i] >>> 4) & 0xF;
int twoHalfs = 0;
do
{
if (0 <= halfByte && halfByte <= 9)
{
buf.append((char) ('0' + halfByte));
}
else
{
buf.append((char) ('a' + halfByte - 10));
}
halfByte = data[i] & 0xF;
}
while (twoHalfs++ < 1);
}
return buf.toString();
}
}
To use it:
ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com", 5222);
config.setSASLAuthenticationEnabled(true);
XMPPConnection xmpp = new XMPPConnection(config);
try
{
SASLAuthentication.registerSASLMechanism("X-FACEBOOK-PLATFORM", SASLXFacebookPlatformMechanism.class);
SASLAuthentication.supportSASLMechanism("X-FACEBOOK-PLATFORM", 0);
xmpp.connect();
xmpp.login(apiKey + "|" + sessionKey, sessionSecret, "Application");
}
catch (XMPPException e)
{
xmpp.disconnect();
e.printStackTrace();
}
apiKey is the API key given in the application settings page in Facebook. sessionKey is the second part of the access token. If the token is in this form, AAA|BBB|CCC, the BBB is the session key. sessionSecret is obtained using the old REST API with the method auth.promoteSession. To use it, it's needed to make a Http get to this url:
https://api.facebook.com/method/auth.promoteSession?access_token=yourAccessToken
Despite of the Facebook Chat documentation says that it's needed to use your application secret key, only when I used the key that returned that REST method I was able to make it works. To make that method works, you have to disable the Disable Deprecated Auth Methods option in the Advance tab in your application settings.
I solved this problem. I find solution that http://community.igniterealtime.org/thread/41080
Jerry Magill wrote this...
import java.io.IOException;
import java.util.HashMap;
import javax.security.auth.callback.CallbackHandler;
import javax.security.sasl.Sasl;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.sasl.SASLMechanism;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.util.Base64;
public class MySASLDigestMD5Mechanism extends SASLMechanism
{
public MySASLDigestMD5Mechanism(SASLAuthentication saslAuthentication)
{
super(saslAuthentication);
}
protected void authenticate()
throws IOException, XMPPException
{
String mechanisms[] = {
getName()
};
java.util.Map props = new HashMap();
sc = Sasl.createSaslClient(mechanisms, null, "xmpp", hostname, props, this);
super.authenticate();
}
public void authenticate(String username, String host, String password)
throws IOException, XMPPException
{
authenticationId = username;
this.password = password;
hostname = host;
String mechanisms[] = {
getName()
};
java.util.Map props = new HashMap();
sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props, this);
super.authenticate();
}
public void authenticate(String username, String host, CallbackHandler cbh)
throws IOException, XMPPException
{
String mechanisms[] = {
getName()
};
java.util.Map props = new HashMap();
sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props, cbh);
super.authenticate();
}
protected String getName()
{
return "DIGEST-MD5";
}
public void challengeReceived(String challenge)
throws IOException
{
//StringBuilder stanza = new StringBuilder();
byte response[];
if(challenge != null)
response = sc.evaluateChallenge(Base64.decode(challenge));
else
//response = sc.evaluateChallenge(null);
response = sc.evaluateChallenge(new byte[0]);
//String authenticationText = "";
Packet responseStanza;
//if(response != null)
//{
//authenticationText = Base64.encodeBytes(response, 8);
//if(authenticationText.equals(""))
//authenticationText = "=";
if (response == null){
responseStanza = new Response();
} else {
responseStanza = new Response(Base64.encodeBytes(response,Base64.DONT_BREAK_LINES));
}
//}
//stanza.append("<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
//stanza.append(authenticationText);
//stanza.append("</response>");
//getSASLAuthentication().send(stanza.toString());
getSASLAuthentication().send(responseStanza);
}
}
It is then called thus from the JabberSmackAPI:
public void login(String userName, String password) throws XMPPException
{
SASLAuthentication.registerSASLMechanism("DIGEST-MD5",MySASLDigestMD5Mechanism. class);
ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com",5222);
config.setSASLAuthenticationEnabled(true);
config.setRosterLoadedAtLogin (true);
connection = new XMPPConnection(config);
connection.connect();
connection.login(userName, password);
}