/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/ package org.apache.catalina.realm;
/** * Implementation of {@link org.apache.catalina.Realm} that is based on an implementation of {@link UserDatabase} made * available through the JNDI resources configured for this instance of Catalina. Set the <code>resourceName</code> * parameter to the JNDI resources name for the configured instance of <code>UserDatabase</code> that we should consult. * * @author Craig R. McClanahan * * @since 4.1
*/ publicclass UserDatabaseRealm extends RealmBase {
/** * The <code>UserDatabase</code> we will use to authenticate users and identify associated roles.
*/ protectedvolatile UserDatabase database = null; privatefinal Object databaseLock = new Object();
/** * The global JNDI name of the <code>UserDatabase</code> resource we will be utilizing.
*/ protected String resourceName = "UserDatabase";
/** * Obtain the UserDatabase from the context (rather than global) JNDI.
*/ privateboolean localJndiResource = false;
/** * Use a static principal disconnected from the database. This prevents live updates to users and roles having an * effect on authenticated principals, but reduces use of the database.
*/ privateboolean useStaticPrincipal = false;
/** * @return the global JNDI name of the <code>UserDatabase</code> resource we will be using.
*/ public String getResourceName() { return resourceName;
}
/** * Set the global JNDI name of the <code>UserDatabase</code> resource we will be using. * * @param resourceName The new global JNDI name
*/ publicvoid setResourceName(String resourceName) { this.resourceName = resourceName;
}
/** * @return the useStaticPrincipal flag
*/ publicboolean getUseStaticPrincipal() { returnthis.useStaticPrincipal;
}
/** * Allows using a static principal disconnected from the user database. * * @param useStaticPrincipal the new value
*/ publicvoid setUseStaticPrincipal(boolean useStaticPrincipal) { this.useStaticPrincipal = useStaticPrincipal;
}
/** * Determines whether this Realm is configured to obtain the associated {@link UserDatabase} from the global JNDI * context or a local (web application) JNDI context. * * @return {@code true} if a local JNDI context will be used, {@code false} if the the global JNDI context will be * used
*/ publicboolean getLocalJndiResource() { return localJndiResource;
}
/** * Configure whether this Realm obtains the associated {@link UserDatabase} from the global JNDI context or a local * (web application) JNDI context. * * @param localJndiResource {@code true} to use a local JNDI context, {@code false} to use the global JNDI context
*/ publicvoid setLocalJndiResource(boolean localJndiResource) { this.localJndiResource = localJndiResource;
}
publicstatic String[] getRoles(User user) {
Set<String> roles = new HashSet<>();
Iterator<Role> uroles = user.getRoles(); while (uroles.hasNext()) {
Role role = uroles.next();
roles.add(role.getName());
}
Iterator<Group> groups = user.getGroups(); while (groups.hasNext()) {
Group group = groups.next();
uroles = group.getRoles(); while (uroles.hasNext()) {
Role role = uroles.next();
roles.add(role.getName());
}
} return roles.toArray(new String[0]);
}
@Override protected Principal getPrincipal(String username) {
UserDatabase database = getUserDatabase(); if (database == null) { returnnull;
}
User user = database.findUser(username); if (user == null) { returnnull;
} else { if (useStaticPrincipal) { returnnew GenericPrincipal(username, Arrays.asList(getRoles(user)));
} else { returnnew UserDatabasePrincipal(user, database);
}
}
}
/* * Can't do this in startInternal() with local JNDI as the local JNDI context won't be initialised at this point.
*/ private UserDatabase getUserDatabase() { // DCL so database MUST be volatile if (database == null) { synchronized (databaseLock) { if (database == null) { try {
Context context = null; if (localJndiResource) {
context = ContextBindings.getClassLoader();
context = (Context) context.lookup("comp/env");
} else {
Server server = getServer(); if (server == null) {
containerLog.error(sm.getString("userDatabaseRealm.noNamingContext")); returnnull;
}
context = getServer().getGlobalNamingContext();
}
database = (UserDatabase) context.lookup(resourceName);
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e); if (containerLog != null) {
containerLog.error(sm.getString("userDatabaseRealm.lookup", resourceName), e);
}
database = null;
}
}
}
} return database;
}
@Override protectedvoid startInternal() throws LifecycleException { // If the JNDI resource is global, check it here and fail the context // start if it is not valid. Local JNDI resources can't be validated // this way because the JNDI context isn't available at Realm start. if (!localJndiResource) {
UserDatabase database = getUserDatabase(); if (database == null) { thrownew LifecycleException(sm.getString("userDatabaseRealm.noDatabase", resourceName));
}
}
@Override public String[] getRoles() { if (database == null) { returnnew String[0];
}
User user = database.findUser(name); if (user == null) { returnnew String[0];
}
Set<String> roles = new HashSet<>();
Iterator<Role> uroles = user.getRoles(); while (uroles.hasNext()) {
Role role = uroles.next();
roles.add(role.getName());
}
Iterator<Group> groups = user.getGroups(); while (groups.hasNext()) {
Group group = groups.next();
uroles = group.getRoles(); while (uroles.hasNext()) {
Role role = uroles.next();
roles.add(role.getName());
}
} return roles.toArray(new String[0]);
}
@Override publicboolean hasRole(String role) { if ("*".equals(role)) { returntrue;
} elseif (role == null) { returnfalse;
} if (database == null) { returnsuper.hasRole(role);
}
Role dbrole = database.findRole(role); if (dbrole == null) { returnfalse;
}
User user = database.findUser(name); if (user == null) { returnfalse;
} if (user.isInRole(dbrole)) { returntrue;
}
Iterator<Group> groups = user.getGroups(); while (groups.hasNext()) {
Group group = groups.next(); if (group.isInRole(dbrole)) { returntrue;
}
} returnfalse;
}
/** * Magic method from {@link java.io.Serializable}. * * @return The object to serialize instead of this object * * @throws ObjectStreamException Not thrown by this implementation
*/ private Object writeReplace() throws ObjectStreamException { // Replace with a static principal disconnected from the database returnnew GenericPrincipal(getName(), Arrays.asList(getRoles()));
}
}
}
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.