📄 jndirealm.java
字号:
}
}
// -------------------------------------------------------- Package Methods
// ------------------------------------------------------ Protected Methods
/**
* Return the Principal associated with the specified username and
* credentials, if there is one; otherwise return <code>null</code>.
*
* @param context The directory context
* @param username Username of the Principal to look up
* @param credentials Password or other credentials to use in
* authenticating this username
*
* @exception NamingException if a directory server error occurs
*/
public synchronized Principal authenticate(DirContext context,
String username,
String credentials)
throws NamingException {
if (username == null || username.equals("")
|| credentials == null || credentials.equals(""))
return (null);
if (userPatternArray != null) {
for (curUserPattern = 0;
curUserPattern < userPatternFormatArray.length;
curUserPattern++) {
// Retrieve user information
User user = getUser(context, username);
if (user != null) {
try {
// Check the user's credentials
if (checkCredentials(context, user, credentials)) {
// Search for additional roles
List roles = getRoles(context, user);
return (new GenericPrincipal(this,
username,
credentials,
roles));
}
} catch (InvalidNameException ine) {
// Log the problem for posterity
log(sm.getString("jndiRealm.exception"), ine);
// ignore; this is probably due to a name not fitting
// the search path format exactly, as in a fully-
// qualified name being munged into a search path
// that already contains cn= or vice-versa
}
}
}
return null;
} else {
// Retrieve user information
User user = getUser(context, username);
if (user == null)
return (null);
// Check the user's credentials
if (!checkCredentials(context, user, credentials))
return (null);
// Search for additional roles
List roles = getRoles(context, user);
// Create and return a suitable Principal for this user
return (new GenericPrincipal(this, username, credentials, roles));
}
}
/**
* Return a User object containing information about the user
* with the specified username, if found in the directory;
* otherwise return <code>null</code>.
*
* If the <code>userPassword</code> configuration attribute is
* specified, the value of that attribute is retrieved from the
* user's directory entry. If the <code>userRoleName</code>
* configuration attribute is specified, all values of that
* attribute are retrieved from the directory entry.
*
* @param context The directory context
* @param username Username to be looked up
*
* @exception NamingException if a directory server error occurs
*/
protected User getUser(DirContext context, String username)
throws NamingException {
User user = null;
// Get attributes to retrieve from user entry
ArrayList list = new ArrayList();
if (userPassword != null)
list.add(userPassword);
if (userRoleName != null)
list.add(userRoleName);
String[] attrIds = new String[list.size()];
list.toArray(attrIds);
// Use pattern or search for user entry
if (userPatternFormatArray != null) {
user = getUserByPattern(context, username, attrIds);
} else {
user = getUserBySearch(context, username, attrIds);
}
return user;
}
/**
* Use the <code>UserPattern</code> configuration attribute to
* locate the directory entry for the user with the specified
* username and return a User object; otherwise return
* <code>null</code>.
*
* @param context The directory context
* @param username The username
* @param attrIds String[]containing names of attributes to
* retrieve.
*
* @exception NamingException if a directory server error occurs
*/
protected User getUserByPattern(DirContext context,
String username,
String[] attrIds)
throws NamingException {
if (debug >= 2)
log("lookupUser(" + username + ")");
if (username == null || userPatternFormatArray[curUserPattern] == null)
return (null);
// Form the dn from the user pattern
String dn = userPatternFormatArray[curUserPattern].format(new String[] { username });
if (debug >= 3) {
log(" dn=" + dn);
}
// Return if no attributes to retrieve
if (attrIds == null || attrIds.length == 0)
return new User(username, dn, null, null);
// Get required attributes from user entry
Attributes attrs = null;
try {
attrs = context.getAttributes(dn, attrIds);
} catch (NameNotFoundException e) {
return (null);
}
if (attrs == null)
return (null);
// Retrieve value of userPassword
String password = null;
if (userPassword != null)
password = getAttributeValue(userPassword, attrs);
// Retrieve values of userRoleName attribute
ArrayList roles = null;
if (userRoleName != null)
roles = addAttributeValues(userRoleName, attrs, roles);
return new User(username, dn, password, roles);
}
/**
* Search the directory to return a User object containing
* information about the user with the specified username, if
* found in the directory; otherwise return <code>null</code>.
*
* @param context The directory context
* @param username The username
* @param attrIds String[]containing names of attributes to retrieve.
*
* @exception NamingException if a directory server error occurs
*/
protected User getUserBySearch(DirContext context,
String username,
String[] attrIds)
throws NamingException {
if (username == null || userSearchFormat == null)
return (null);
// Form the search filter
String filter = userSearchFormat.format(new String[] { username });
// Set up the search controls
SearchControls constraints = new SearchControls();
if (userSubtree) {
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
constraints.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
// Specify the attributes to be retrieved
if (attrIds == null)
attrIds = new String[0];
constraints.setReturningAttributes(attrIds);
if (debug > 3) {
log(" Searching for " + username);
log(" base: " + userBase + " filter: " + filter);
}
NamingEnumeration results =
context.search(userBase, filter, constraints);
// Fail if no entries found
if (results == null || !results.hasMore()) {
if (debug > 2) {
log(" username not found");
}
return (null);
}
// Get result for the first entry found
SearchResult result = (SearchResult)results.next();
// Check no further entries were found
if (results.hasMore()) {
log("username " + username + " has multiple entries");
return (null);
}
// Get the entry's distinguished name
NameParser parser = context.getNameParser("");
Name contextName = parser.parse(context.getNameInNamespace());
Name baseName = parser.parse(userBase);
Name entryName = parser.parse(result.getName());
Name name = contextName.addAll(baseName);
name = name.addAll(entryName);
String dn = name.toString();
if (debug > 2)
log(" entry found for " + username + " with dn " + dn);
// Get the entry's attributes
Attributes attrs = result.getAttributes();
if (attrs == null)
return null;
// Retrieve value of userPassword
String password = null;
if (userPassword != null)
password = getAttributeValue(userPassword, attrs);
// Retrieve values of userRoleName attribute
ArrayList roles = null;
if (userRoleName != null)
roles = addAttributeValues(userRoleName, attrs, roles);
return new User(username, dn, password, roles);
}
/**
* Check whether the given User can be authenticated with the
* given credentials. If the <code>userPassword</code>
* configuration attribute is specified, the credentials
* previously retrieved from the directory are compared explicitly
* with those presented by the user. Otherwise the presented
* credentials are checked by binding to the directory as the
* user.
*
* @param context The directory context
* @param user The User to be authenticated
* @param credentials The credentials presented by the user
*
* @exception NamingException if a directory server error occurs
*/
protected boolean checkCredentials(DirContext context,
User user,
String credentials)
throws NamingException {
boolean validated = false;
if (userPassword == null) {
validated = bindAsUser(context, user, credentials);
} else {
validated = compareCredentials(context, user, credentials);
}
if (debug >= 2) {
if (validated) {
log(sm.getString("jndiRealm.authenticateSuccess",
user.username));
} else {
log(sm.getString("jndiRealm.authenticateFailure",
user.username));
}
}
return (validated);
}
/**
* Check whether the credentials presented by the user match those
* retrieved from the directory.
*
* @param context The directory context
* @param user The User to be authenticated
* @param credentials Authentication credentials
*
* @exception NamingException if a directory server error occurs
*/
protected boolean compareCredentials(DirContext context,
User info,
String credentials)
throws NamingException {
if (info == null || credentials == null)
return (false);
String password = info.password;
if (password == null)
return (false);
// Validate the credentials specified by the user
if (debug >= 3)
log(" validating credentials");
boolean validated = false;
if (hasMessageDigest()) {
// iPlanet support if the values starts with {SHA1}
// The string is in a format compatible with Base64.encode not
// the Hex encoding of the parent class.
if (password.startsWith("{SHA}")) {
/* sync since super.digest() does this same thing */
synchronized (this) {
password = password.substring(5);
md.reset();
md.update(credentials.getBytes());
String digestedPassword =
new String(Base64.encode(md.digest()));
validated = password.equals(digestedPassword);
}
} else {
// Hex hashes should be compared case-insensitive
validated = (digest(credentials).equalsIgnoreCase(password));
}
} else
validated = (digest(credentials).equals(password));
return (validated);
}
/**
* Check credentials by binding to the directory as the user
*
* @param context The directory context
* @param user The User to be authenticated
* @param credentials Authentication credentials
*
* @exception NamingException if a directory server error occurs
*/
protected boolean bindAsUser(DirContext context,
User user,
String credentials)
throws NamingException {
Attributes attr;
if (credentials == null || user == null)
return (false);
String dn = user.dn;
if (dn == null)
return (false);
// Validate the credentials specified by the user
if (debug >= 3) {
log(" validating credentials by binding as the user");
}
// Set up security environment to bind as the user
context.addToEnvironment(Context.SECURITY_PRINCIPAL, dn);
context.addToEnvironment(Context.SECURITY_CREDENTIALS, credentials);
// Elicit an LDAP bind operation
boolean validated = false;
try {
if (debug > 2) {
log(" binding as " + dn);
}
attr = context.getAttributes("", null);
validated = true;
}
catch (AuthenticationException e) {
if (debug > 2) {
log(" bind attempt failed");
}
}
// Restore the original security environment
if (connectionName != null) {
context.addToEnvironment(Context.SECURITY_PRINCIPAL,
connectionName);
} else {
context.removeFromEnvironment(Context.SECURITY_PRINCIPAL);
}
if (connectionPassword != null) {
context.addToEnvironment(Context.SECURITY_CREDENTIALS,
connectionPassword);
}
else {
context.removeFromEnvironment(Context.SECURITY_CREDENTIALS);
}
return (validated);
}
/**
* Return a List of roles associated with the given User. Any
* roles present in the user's directory entry are supplemented by
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -