--- java/org/apache/catalina/realm/LocalStrings.properties (Revision 1519167) +++ java/org/apache/catalina/realm/LocalStrings.properties (Arbeitskopie) @@ -58,6 +58,12 @@ jndiRealm.exception=Exception performing authentication jndiRealm.exception.retry=Exception performing authentication. Retrying... jndiRealm.open=Exception opening directory server connection +mappingRealm.fileNotExists=Realm mapping file {0} does not exist. No security role will be available +mappingRealm.invalidMapping=Invalid syntax in mapping [{0}] +mappingRealm.loadFailed=Could not Realm mapping file {0} +mappingRealm.loadOK=Loaded Realm mapping file {0} +mappingRealm.loadRoleMappings=Load role mappings from configuration, ignore {0} +mappingRealm.mapped=Mapped application security role [{0}] to realm security role [{1}] memoryRealm.authenticateFailure=Username {0} NOT successfully authenticated memoryRealm.authenticateSuccess=Username {0} successfully authenticated memoryRealm.loadExist=Memory database file {0} cannot be read --- java/org/apache/catalina/realm/MappingRealm.java (Revision 0) +++ java/org/apache/catalina/realm/MappingRealm.java (Arbeitskopie) @@ -0,0 +1,273 @@ +/* + * 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; + +import java.security.Principal; +import java.util.Properties; +import java.io.IOException; +import java.io.File; +import java.io.FileInputStream; + +import org.apache.catalina.Globals; +import org.apache.catalina.Wrapper; +import org.apache.catalina.LifecycleException; +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; + +/** + */ + +public class MappingRealm extends CombinedRealm { + + private static final Log log = LogFactory.getLog(MappingRealm.class); + + + // ----------------------------------------------------- Instance Variables + + /** + * Internal security role translation + */ + protected Properties mapping = null; + + /** + * Filename to load mapping from + * Format is application-security-role=inner-realm-security-role + */ + protected String pathname = "conf/mapping.properties"; + + /* + * Symbol or string used as assignment operator when using roleMappings + * Default: = + */ + protected String assignment = "="; + + /* + * Symbol or string used as separator between different assignments when using roleMappings + * Default: ; + */ + protected String separator = ";"; + + /** + * String with role mappings. If this is set the properties file is ignored + */ + protected String roleMappings = null; + + /** + * Descriptive information about this Realm implementation. + */ + protected static final String info = + "org.apache.catalina.realm.MappingRealm/1.0"; + + /** + * Descriptive information about this Realm implementation. + */ + protected static final String name = "MappingRealm"; + + /** + * Return descriptive information about this Realm implementation and + * the corresponding version number, in the format + * <description>/<version>. + */ + @Override + public String getInfo() { + + return info; + + } + + /** + * Return a short name for this Realm implementation. + */ + @Override + protected String getName() { + + return (name); + + } + + /** + * Get assignment string + */ + public String getAssignment() { + return assignment; + } + + /** + * Set assignment string + */ + public void setAssignment(String assignment) { + this.assignment=assignment; + } + + /** + * Get separator string + */ + public String getSeparator() { + return separator; + } + + /** + * Set separator string + */ + public void setSeparator(String separator) { + this.separator=separator; + } + + /** + * Get mapping rule string + */ + public String getRoleMappings() { + return roleMappings; + } + + /** + * Set separator string + */ + public void setRoleMappings(String roleMappings) { + this.roleMappings=roleMappings; + } + + /** + * Get pathname of mapping properties files + */ + public String getPathname() { + return pathname; + } + + /** + * Set pathname for properties file to load + */ + public void setPathname(String pathname) { + this.pathname = pathname; + } + + // ---------------------------------------------------------- Realm Methods + + /** + * Return true if the specified Principal has the specified + * security role, within the context of this Realm; otherwise return + * false. This method can be overridden by Realm + * implementations, but the default is adequate when an instance of + * GenericPrincipal is used to represent authenticated + * Principals from this Realm. + * + * @param principal Principal for whom the role is to be checked + * @param role Security role to be checked + */ + @Override + public boolean hasRole(Wrapper wrapper, Principal principal, String role) { + + // Copied from GenericPrincipal + if("*".equals(role)) { // Special 2.4 role meaning everyone + return true; + } + if (role == null) { + return (false); + } + + String mappedRole = mapping.getProperty(role); + + if((mappedRole != null) && super.hasRole(wrapper, principal, mappedRole)) { + if (log.isDebugEnabled()) { + log.debug(sm.getString("mappingRealm.mapped", role, mappedRole)); + } + return true; + } else { + return false; + } + } + + + // ------------------------------------------------------ Lifecycle Methods + + + /** + * Prepare for the beginning of active use of the public methods of this + * component and implement the requirements of + * {@link org.apache.catalina.util.LifecycleBase#startInternal()}. + * + * @exception LifecycleException if this component detects a fatal error + * that prevents this component from being used + */ + @Override + protected void startInternal() throws LifecycleException { + + mapping = new Properties(); + + if (roleMappings != null) { + log.info(sm.getString("mappingRealm.loadRoleMappings",pathname)); + for (String entry : roleMappings.split(separator)) { + String[] kv = entry.split(assignment, 2); + if (kv.length == 2) { + mapping.setProperty(kv[0], kv[1]); + } else { + log.error(sm.getString("mappingRealm.invalidMapping",entry)); + } + } + } else { + File file = new File(pathname); + if (!file.isAbsolute()) { + file = new File(System.getProperty(Globals.CATALINA_BASE_PROP), + pathname); + } + if (file.exists()) { + FileInputStream fis = null; + try { + fis = new FileInputStream(file); + mapping.load(fis); + log.info(sm.getString("mappingRealm.loadOK", pathname)); + } catch (IOException ioe) { + log.error(sm.getString("mappingRealm.loadFailed", pathname)); + } finally { + if (fis != null) { + try { + fis.close(); + } catch (IOException ioe) { + // Ignore + } + } + } + } else { + log.error(sm.getString("mappingRealm.fileNotExists", pathname)); + } + } + + super.startInternal(); + } + + + /** + * Gracefully terminate the active use of the public methods of this + * component and implement the requirements of + * {@link org.apache.catalina.util.LifecycleBase#stopInternal()}. + * + * @exception LifecycleException if this component detects a fatal error + * that needs to be reported + */ + @Override + protected void stopInternal() throws LifecycleException { + + // Perform normal superclass finalization + super.stopInternal(); + + // Release mappings + mapping = null; + roleMappings = null; + } +} +