📄 jndiops.java
字号:
{
// sanity check
if (url == null)
throw new NamingException("URL not specified in openContext()!");
// set the tracing level now, since (wierdly) it can't be set once the connection is open.
if (tracing)
env.put("com.sun.jndi.ldap.trace.ber", System.err);
env.put("java.naming.ldap.version", "3"); // always use ldap v3
if (env.get(Context.INITIAL_CONTEXT_FACTORY) == null)
env.put(Context.INITIAL_CONTEXT_FACTORY, DEFAULT_CTX); // use jndi provider
env.put("java.naming.ldap.deleteRDN", "false"); // usually what we want
env.put(Context.REFERRAL, referralType); //could be: follow, ignore, throw
env.put("java.naming.ldap.attributes.binary", "photo jpegphoto jpegPhoto"); // special hack to handle non-standard binary atts
env.put("java.naming.ldap.derefAliases", aliasType); // could be: finding, searching, etc.
env.put(Context.SECURITY_AUTHENTICATION, "none"); // no authentication (may be modified by other code)
env.put(Context.PROVIDER_URL, url); // the ldap url to connect to; e.g. "ldap://ca.com:389"
}
/**
* This sets the environment properties needed for a simple username +
* password authenticated jndi connection. It is used by openSimpleSecurityContext().
* <p/>
* This method is provided as a convenience for people wishing to append
* or modify the jndi environment, without setting it up entirely from
* scratch.
*
* @param env
* @param userDN
* @param pwd
*/
public static void setupSimpleSecurityProperties(Hashtable env, String userDN, char[] pwd)
{
env.put(Context.SECURITY_AUTHENTICATION, "simple"); // 'simple' = username + password
env.put(Context.SECURITY_PRINCIPAL, userDN); // add the full user dn
env.put(Context.SECURITY_CREDENTIALS, new String(pwd)); // stupid jndi requires us to cast this to a string-
// this opens a security weakness with swapped memory etc.
}
/**
* @param env
* @param cacerts
* @param clientcerts
* @param caKeystorePwd
* @param clientKeystorePwd
* @param caKeystoreType
* @param clientKeystoreType
* @param tracing
* @param sslTracing
* @param sslSocketFactory
* @throws NamingException
* @deprecated - use the version without the tracing flag (set in setupBasicProperties).
*/
public static void setupSSLProperties(Hashtable env,
String cacerts, String clientcerts,
char[] caKeystorePwd, char[] clientKeystorePwd,
String caKeystoreType, String clientKeystoreType,
boolean tracing, boolean sslTracing,
String sslSocketFactory)
throws NamingException
{
setupSSLProperties(env, cacerts, clientcerts, caKeystorePwd, clientKeystorePwd, caKeystoreType, clientKeystoreType, sslTracing, sslSocketFactory);
}
/* This static ftn. sets the environment used to open an SSL or SASL context.
* It is used by openSSLContext.
*
* If only SSL is desired, the clientcerts, clientKeystorePwd and clientKeystoreType
* variables may be set to null.
*
* This method is provided as a convenience for people wishing to append
* or modify the jndi environment, without setting it up entirely from
* scratch.
*
* @param url a url of the form ldap://hostname:portnumber.
* @param tracing whether to set BER tracing on or not.
* @param cacerts the file containing the trusted server certificates (no keys).
* @param clientcerts the file containing client certificates.
* @param caKeystorePwd the password to the ca's keystore (may be null for non-client authenticated ssl).
* @param clientKeystorePwd the password to the client's keystore (may be null for non-client authenticated ssl).
* @param caKeystoreType the type of keystore file; e.g. 'JKS', or 'PKCS12'.
* @param clientKeystoreType the type of keystore file; e.g. 'JKS', or 'PKCS12'.
*
* @return The created context.
*/
public static void setupSSLProperties(Hashtable env,
String cacerts, String clientcerts,
char[] caKeystorePwd, char[] clientKeystorePwd,
String caKeystoreType, String clientKeystoreType,
boolean sslTracing,
String sslSocketFactory)
throws NamingException
{
// sanity check
if (cacerts == null)
throw new NamingException("Cannot use SSL without a trusted CA certificates JKS file.");
// the exact protocol (e.g. "TLS") set in JndiSocketFactory
env.put(Context.SECURITY_PROTOCOL, "ssl");
// Initialise the SSL Socket Factory. Due to architectural wierdnesses, this is
// a separate, static method in our own separate SSL Factory class.
if (sslSocketFactory.equals("com.ca.commons.jndi.JndiSocketFactory"))
{
JndiSocketFactory.init(cacerts, clientcerts,
caKeystorePwd, clientKeystorePwd,
caKeystoreType, clientKeystoreType);
}
// Tell JNDI to use our own, separate SSL Factory class with the keystores set as previously
env.put("java.naming.ldap.factory.socket", sslSocketFactory);
// try to use client authentication (SASL) if a clientcert keystore and pwd supplied
if (clientcerts != null && (clientKeystorePwd != null && clientKeystorePwd.length > 0))
{
env.put(Context.SECURITY_AUTHENTICATION, "EXTERNAL"); // Use sasl external (i.e., certificate) auth
}
if (sslTracing)
{
// XXX doesn't seem to work?
System.setProperty("javax.net.debug", "ssl handshake verbose");
}
}
/**
* This is a raw interface to javax.naming.directory.InitialDirContext, that allows
* an arbitrary environment string to be passed through. Often it will be
* convenient to create that environment list using a set...Properties call (or just
* use one of the constructors to create a JNDIOps object.
*
* @param env a list of environment variables for the context
* @return a newly created DirContext.
*/
public static DirContext openContext(Hashtable env)
throws NamingException
{
/* DEBUG code - do not remove
System.out.println("-- listing properties --");
for (Enumeration e = env.keys() ; e.hasMoreElements() ;)
{
String key = e.nextElement().toString();
String val = env.get(key).toString();
if (val.length() > 40) {
val = val.substring(0, 37) + "...";
}
System.out.println(key + "=" + val);
}
System.out.println("-- end list --");
*/
DirContext ctx = new InitialDirContext(env);
if (ctx == null)
throw new NamingException("Internal Error with jndi connection: No Context was returned, however no exception was reported by jndi.");
return ctx;
}
/**
* <p>A wrapper for context.rename... changes the
* distinguished name of an object, checks for error.
* !! Only changes the final RDN.</p>
* <p/>
* <p>WARNING! this will fail for single valued manditory attributes.
* since using 'deleteRDN = false' - use renameEntry(old, new, deleteOldRdn)
* method instead - 30 May 2002.</p>
*
* @param oldDN current distinguished name of an object.
* @param newDN the name it is to be changed to.
*/
public void renameEntry(Name oldDN, Name newDN)
throws NamingException
{
Name rdn = newDN.getSuffix(newDN.size() - 1);
Name oldRdn = oldDN.getSuffix(oldDN.size() - 1);
if (oldRdn.toString().equals(rdn.toString()) == false) // do nothing if names the same.
ctx.rename(oldDN, rdn);
}
/**
* Copies an object to a new DN by the simple expedient of adding
* an object with the new DN, and the attributes of the old object.
*
* @param fromDN the original object being copied
* @param toDN the new object being created
*/
public void copyEntry(Name fromDN, Name toDN)
throws NamingException
{
addEntry(toDN, read(fromDN));
}
/**
* creates a new object (subcontext) with the given
* dn and attributes.
*
* @param dn the distinguished name of the new object
* @param atts attributes for the new object
*/
public void addEntry(Name dn, Attributes atts)
throws NamingException
{
ctx.createSubcontext(dn, atts);
}
/**
* deletes a leaf entry (subcontext). It is
* an error to attempt to delete an entry which is not a leaf
* entry, i.e. which has children.
*/
public void deleteEntry(Name dn)
throws NamingException
{
ctx.destroySubcontext(dn);
}
/**
* Checks the existence of a particular DN, without (necessarily)
* reading any attributes.
*
* @param nodeDN the DN to check
* @return the existence of the nodeDN (or false if an error occurs).
*/
public boolean exists(Name nodeDN)
throws NamingException
{
try
{
ctx.search(nodeDN, "(objectclass=*)", existanceConstraints);
return true;
}
catch (NoSuchAttributeException e) // well, there has to be an entry for us not to find attributes on right?
{ // so maybe it's an exchange server, or has weird visibility permissions...
return true;
}
catch (NameNotFoundException e) // ugly as sin, but there seems no other way of doing things
{
return false;
}
/*
* This is what is known in the programming trade as 'a filthy hack'. There is a bug in the Sun DSML provider
* where a null pointer exception is thrown at com.sun.jndi.dsmlv2.soap.DsmlSoapCtx.c_lookup(DsmlSoapCtx.java:571)
* (possibly when a referral is returned?). For our purposes though it translates to 'not found' - so we intercept
* the bug and return false instead...
*/
catch (NullPointerException e)
{
if ((ctx != null) && (ctx.getEnvironment().get(Context.INITIAL_CONTEXT_FACTORY).toString().indexOf("dsml") > 0))
return false;
else
throw e;
}
}
/**
* Checks the existence of a particular DN, without (necessarily)
* reading any attributes.
*
* @param nodeDN the DN to check
* @return the existence of the nodeDN (or false if an error occurs).
*/
public boolean exists(String nodeDN)
throws NamingException
{
try
{
ctx.search(nodeDN, "(objectclass=*)", existanceConstraints);
return true;
}
catch (NameNotFoundException e) // ugly as sin, but there seems no other way of doing things
{
return false;
}
/*
* This is what is known in the programming trade as 'a filthy hack'. There is a bug in the Sun DSML provider
* where a null pointer exception is thrown at com.sun.jndi.dsmlv2.soap.DsmlSoapCtx.c_lookup(DsmlSoapCtx.java:571)
* (possibly when a referral is returned?). For our purposes though it translates to 'not found' - so we intercept
* the bug and return false instead...
*/
catch (NullPointerException e)
{
if ((ctx != null) && (ctx.getEnvironment().get(Context.INITIAL_CONTEXT_FACTORY).toString().indexOf("dsml") > 0))
return false;
else
throw e;
}
}
/**
* Reads all the attribute type and values for the given entry.
*
* @param dn the ldap string distinguished name of entry to be read
* @return an 'Attributes' object containing a list of all Attribute
* objects.
*/
public synchronized Attributes read(Name dn)
throws NamingException
{
return read(dn, null);
}
/**
* Reads all the attribute type and values for the given entry.
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -