📄 jndirealm.java
字号:
// 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 (username == null || userPatternFormatArray[curUserPattern] == null)
return (null);
// Form the dn from the user pattern
String dn = userPatternFormatArray[curUserPattern].format(new String[] { username });
// 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);
NamingEnumeration results =
context.search(userBase, filter, constraints);
// Fail if no entries found
if (results == null || !results.hasMore()) {
return (null);
}
// Get result for the first entry found
SearchResult result = (SearchResult)results.next();
// Check no further entries were found
if (results.hasMore()) {
if(containerLog.isInfoEnabled())
containerLog.info("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);
// Bugzilla 32269
Name entryName = parser.parse(new CompositeName(result.getName()).get(0));
Name name = contextName.addAll(baseName);
name = name.addAll(entryName);
String dn = name.toString();
if (containerLog.isTraceEnabled())
containerLog.trace(" 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 (containerLog.isTraceEnabled()) {
if (validated) {
containerLog.trace(sm.getString("jndiRealm.authenticateSuccess",
user.username));
} else {
containerLog.trace(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 info 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 (containerLog.isTraceEnabled())
containerLog.trace(" 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 if (password.startsWith("{SSHA}")) {
// Bugzilla 32938
/* sync since super.digest() does this same thing */
synchronized (this) {
password = password.substring(6);
md.reset();
md.update(credentials.getBytes());
// Decode stored password.
ByteChunk pwbc = new ByteChunk(password.length());
try {
pwbc.append(password.getBytes(), 0, password.length());
} catch (IOException e) {
// Should never happen
containerLog.error("Could not append password bytes to chunk: ", e);
}
CharChunk decoded = new CharChunk();
Base64.decode(pwbc, decoded);
char[] pwarray = decoded.getBuffer();
// Split decoded password into hash and salt.
final int saltpos = 20;
byte[] hash = new byte[saltpos];
for (int i=0; i< hash.length; i++) {
hash[i] = (byte) pwarray[i];
}
byte[] salt = new byte[pwarray.length - saltpos];
for (int i=0; i< salt.length; i++)
salt[i] = (byte)pwarray[i+saltpos];
md.update(salt);
byte[] dp = md.digest();
validated = Arrays.equals(dp, hash);
} // End synchronized(this) block
} 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 (containerLog.isTraceEnabled()) {
containerLog.trace(" 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 (containerLog.isTraceEnabled()) {
containerLog.trace(" binding as " + dn);
}
attr = context.getAttributes("", null);
validated = true;
}
catch (AuthenticationException e) {
if (containerLog.isTraceEnabled()) {
containerLog.trace(" 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
* a directory search. If no roles are associated with this user,
* a zero-length List is returned.
*
* @param context The directory context we are searching
* @param user The User to be checked
*
* @exception NamingException if a directory server error occurs
*/
protected List getRoles(DirContext context, User user)
throws NamingException {
if (user == null)
return (null);
String dn = user.dn;
String username = user.username;
if (dn == null || username == null)
return (null);
if (containerLog.isTraceEnabled())
containerLog.trace(" getRoles(" + dn + ")");
// Start with roles retrieved from the user entry
ArrayList list = user.roles;
if (list == null) {
list = new ArrayList();
}
// Are we configured to do role searches?
if ((roleFormat == null) || (roleName == null))
return (list);
// Set up parameters for an appropriate search
String filter = roleFormat.format(new String[] { doRFC2254Encoding(dn), username });
SearchControls controls = new SearchControls();
if (roleSubtree)
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
else
controls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
controls.setReturningAttributes(new String[] {roleName});
// Perform the configured search and process the results
NamingEnumeration results =
context.search(roleBase, filter, controls);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -