📄 jndiops.java
字号:
package com.ca.commons.jndi;
import javax.naming.*;
import javax.naming.directory.*;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.security.auth.Subject;
import java.util.*;
import java.util.logging.Logger;
/**
* <p>JNDI Ops is a bare-bones utility class that takes up some
* of the over-head of making jndi calls. It is used by
* BasicOps which adds validation, error handling and logging.<p>
* <p/>
* <p>This utility class assumes you will be using ldap v3 with
* the environment defaults:
* "java.naming.ldap.deleteRDN" = "false"
* Context.REFERRAL (java.naming.referral), "ignore");
* java.naming.ldap.attributes.binary", "photo jpegphoto jpegPhoto");
* java.naming.ldap.derefAliases", "finding");
*/
public class JNDIOps
{
private static final String DEFAULT_CTX = "com.sun.jndi.ldap.LdapCtxFactory";
/**
* To speed up existance checks, we use a single static constraints object that
* never changes.
*/
private SearchControls existanceConstraints;
/**
* How to handle ldap referrals if unspecified
*/
public static final String DEFAULT_REFERRAL_HANDLING = "ignore";
/**
* How to handle ldap aliases if unspecified
*/
public static final String DEFAULT_ALIAS_HANDLING = "finding";
// we may wish to extend this class to opening DSML connections in future.
//private static final String DEFAULT_DSML_CTX = "com.sun.jndi.dsmlv2.soap.DsmlSoapCtxFactory";
private NameParser nameParser;
//AJR: converted protected member variable into private, added getContext / setContext accessors.
//NOTE: used Context rather than Ctx to match existing getContext() in BasicOps
private DirContext ctx = null;
private static Logger log = Logger.getLogger(JNDIOps.class.getName()); // ...It's round it's heavy it's wood... It's better than bad, it's good...
// initialise a reusable static constraints object for fast existance searching in 'exists()' methods
{
existanceConstraints = new SearchControls();
existanceConstraints.setSearchScope(SearchControls.OBJECT_SCOPE);
existanceConstraints.setCountLimit(0);
existanceConstraints.setTimeLimit(0);
existanceConstraints.setReturningAttributes(new String[]{"1.1"}); // just the names Madam
}
/**
* Initialise a Basic Operation object with a context.
*/
public JNDIOps(DirContext c)
{
setContext(c);
}
/**
* This creates a jndi connection with a particular set of environment properties.
* Often this will be obtained by using one of the set...Properties methods to
* create a base list of properties and then modifing it before calling this
* constructor.
*/
/**
* This creates a jndi connection with a particular set of environment properties.
* Often this will be obtained by using one of the set...Properties methods to
* create a base list of properties and then modifing it before calling this
* constructor.
*/
public JNDIOps(Hashtable env) throws NamingException
{
// GSSAPI/Kerberos code from Vadim Tarassov
// TODO: consider refactoring to make this handling
// similar to other setup... methods? Maybe in CBOpenConWin?
if ((env.get(Context.SECURITY_AUTHENTICATION)).equals("GSSAPI"))
{
setupKerberosContext(env);
}
else
{
setContext(openContext(env)); // create the connection!
}
}
/**
* This creates an ldap context using GSSAPI/Kerberos for
* security. It uses cached kerberos credentials, or
* calls JXCallbackHandler() to obtain credentials if none
* are already available.
* @param env
* @throws NamingException
*/
protected void setupKerberosContext(Hashtable env)
throws NamingException
{
// debug
log.finest("dumping kerberos environment keys");
Enumeration keys = env.keys();
while (keys.hasMoreElements())
{
String key = (String)keys.nextElement();
log.finest(key + " : " + env.get(key));
}
// Create LoginContext
LoginContext lc = null;
try
{
lc = new LoginContext(JNDIOps.class.getName(),
new JXCallbackHandler());
lc.login();
}
catch (LoginException ex)
{
ex.printStackTrace();
throw new NamingException("login problem: " + ex);
}
DirContext newCtx = (DirContext) Subject.doAs(lc.getSubject(), new JndiAction(env));
if (newCtx == null)
{
throw new NamingException("a problem with GSSAPI occurred - couldn't create a GSSAPI directory context");
} // Vadim: other then GSSAPI
setContext(newCtx);
if (ctx == null)
{
throw new NamingException("another problem with GSSAPI occurred"); // usually caught by the first error
} // Vadim: other then GSSAPI
}
/**
* This creates a simple, unauthenticated jndi connection to an ldap url.
* Note that this ftn may take some time to return...
*
* @param url a url of the form ldap://hostname:portnumber.
*/
public JNDIOps(String url)
throws NamingException
{
Hashtable env = new Hashtable(); // an environment for jndi context parameters
setupBasicProperties(env, url); // set up the bare minimum parameters
setContext(openContext(env)); // create the connection!
}
/**
* <p>This creates a JNDIOps object using simple username + password authentication.</p>
* <p/>
* <p>This constructor opens an initial context. Note that this ftn may take some
* time to return...</p>
*
* @param url a url of the form ldap://hostname:portnumber.
* @param userDN the Manager User's distinguished name (optionally null if not used).
* @param pwd the Manager User's password - (is null if user is not manager).
*/
public JNDIOps(String url, String userDN, char[] pwd)
throws NamingException
{
Hashtable env = new Hashtable(); // an environment for jndi context parameters
setupBasicProperties(env, url); // set up the bare minimum parameters
setupSimpleSecurityProperties(env, userDN, pwd); // add the username + password parameters
setContext(openContext(env)); // create the connection !
}
/**
* This creates a JNDIOps object with an SSL or SASL Connection.
* <p/>
* If only SSL is desired, the clientcerts, clientKeystorePwd and clientKeystoreType
* variables may be set to null.
*
* @param url a url of the form ldap://hostname:portnumber.
* @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'.
* @param tracing whether to set BER tracing on or not.
* @param sslTracing whether to set SSL tracing on or not.
*/
public JNDIOps(String url,
String cacerts, String clientcerts,
char[] caKeystorePwd, char[] clientKeystorePwd,
String caKeystoreType, String clientKeystoreType,
boolean tracing, boolean sslTracing, String sslSocketFactory)
throws NamingException
{
Hashtable env = new Hashtable(); // an environment for jndi context parameters
setupBasicProperties(env, url, tracing, DEFAULT_REFERRAL_HANDLING, DEFAULT_ALIAS_HANDLING); // set up the bare minimum parameters
// add the SSL ('ca...') and possible SASL ('client...') parameters
setupSSLProperties(env, cacerts, clientcerts,
caKeystorePwd, clientKeystorePwd,
caKeystoreType, clientKeystoreType,
sslTracing, sslSocketFactory);
setContext(openContext(env)); // create the connection !
}
/**
* @param env
* @param url
* @throws NamingException
*/
public static void setupBasicProperties(Hashtable env, String url)
throws NamingException
{
setupBasicProperties(env, url, false, DEFAULT_REFERRAL_HANDLING, DEFAULT_ALIAS_HANDLING);
}
/**
* This method combines a serverURL (e.g. ldap://localhost:19389) with a base DN to
* start searching from (e.g. o=democorp,c=au) to create a full ldap URL
* (e.g. ldap://localhost:19389/o=democorp,c=au. It does some of the required
* escaping to the baseDN, but does not formally check either the DN or the
* serverURL for correctness.
*
* see RFC 2252 for more details.
* @param serverURL
* @param baseDN
* @return
*/
/* from RFC 1738 2.2
Unsafe:
Characters can be unsafe for a number of reasons. The space
character is unsafe because significant spaces may disappear and
insignificant spaces may be introduced when URLs are transcribed or
typeset or subjected to the treatment of word-processing programs.
The characters "<" and ">" are unsafe because they are used as the
delimiters around URLs in free text; the quote mark (""") is used to
delimit URLs in some systems. The character "#" is unsafe and should
always be encoded because it is used in World Wide Web and in other
systems to delimit a URL from a fragment/anchor identifier that might
follow it. The character "%" is unsafe because it is used for
encodings of other characters. Other characters are unsafe because
gateways and other transport agents are known to sometimes modify
such characters. These characters are "{", "}", "|", "\", "^", "~",
"[", "]", and "`".
*/
public static String makeServerURL(String serverURL, String baseDN)
{
if (baseDN != null && baseDN.length() > 0)
{
// trim any extra '/' on the end of the server URL (we add it back below)
if (serverURL.length()>7 && serverURL.endsWith("/"))
serverURL = serverURL.substring(0, serverURL.length()-1);
// XXX really important that this one happens first!!
baseDN = baseDN.replaceAll("[%]", "%25");
baseDN = baseDN.replaceAll(" ", "%20");
baseDN = baseDN.replaceAll("[<]", "%3c");
baseDN = baseDN.replaceAll("[>]", "%3e");
baseDN = baseDN.replaceAll("[\"]", "%3f");
baseDN = baseDN.replaceAll("[#]", "%23");
baseDN = baseDN.replaceAll("[{]", "%7b");
baseDN = baseDN.replaceAll("[}]", "%7d");
baseDN = baseDN.replaceAll("[|]", "%7c");
baseDN = baseDN.replaceAll("[\\\\]", "%5c"); // double check this one :-)
baseDN = baseDN.replaceAll("[\\^]", "%5e");
baseDN = baseDN.replaceAll("[~]", "%7e");
baseDN = baseDN.replaceAll("[\\[]", "%5b");
baseDN = baseDN.replaceAll("[\\]]", "%5d");
baseDN = baseDN.replaceAll("[']", "%27");
baseDN = baseDN.replaceAll("[?]", "%3f");
serverURL = serverURL + "/" + baseDN;
}
return serverURL;
}
/**
* This sets the basic environment properties needed for a simple,
* unauthenticated jndi connection. It is used by openBasicContext().
* <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 url
* @param env
* @throws NamingException
*/
public static void setupBasicProperties(Hashtable env, String url, boolean tracing, String referralType, String aliasType)
throws NamingException
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -