| // ======================================================================== |
| // $Id: HashUserRealm.java,v 1.29 2005/08/13 00:01:24 gregwilkins Exp $ |
| // Copyright 1996-2004 Mort Bay Consulting Pty. Ltd. |
| // ------------------------------------------------------------------------ |
| // Licensed 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.openqa.jetty.http; |
| |
| import java.io.Externalizable; |
| import java.io.IOException; |
| import java.io.PrintStream; |
| import java.security.Principal; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.StringTokenizer; |
| |
| import org.apache.commons.logging.Log; |
| import org.openqa.jetty.log.LogFactory; |
| import org.openqa.jetty.util.Credential; |
| import org.openqa.jetty.util.Password; |
| import org.openqa.jetty.util.Resource; |
| |
| /* ------------------------------------------------------------ */ |
| /** HashMapped User Realm. |
| * |
| * An implementation of UserRealm that stores users and roles in-memory in |
| * HashMaps. |
| * <P> |
| * Typically these maps are populated by calling the load() method or passing |
| * a properties resource to the constructor. The format of the properties |
| * file is: <PRE> |
| * username: password [,rolename ...] |
| * </PRE> |
| * Passwords may be clear text, obfuscated or checksummed. The class |
| * com.mortbay.Util.Password should be used to generate obfuscated |
| * passwords or password checksums. |
| * |
| * If DIGEST Authentication is used, the password must be in a recoverable |
| * format, either plain text or OBF:. |
| * |
| * The HashUserRealm also implements SSORealm but provides no implementation |
| * of SSORealm. Instead setSSORealm may be used to provide a delegate |
| * SSORealm implementation. |
| * |
| * @see Password |
| * @version $Id: HashUserRealm.java,v 1.29 2005/08/13 00:01:24 gregwilkins Exp $ |
| * @author Greg Wilkins (gregw) |
| */ |
| public class HashUserRealm |
| extends HashMap |
| implements UserRealm, SSORealm, Externalizable |
| { |
| private static Log log = LogFactory.getLog(HashUserRealm.class); |
| |
| /** HttpContext Attribute to set to activate SSO. |
| */ |
| public static final String __SSO = "org.openqa.jetty.http.SSO"; |
| |
| /* ------------------------------------------------------------ */ |
| private String _realmName; |
| private String _config; |
| protected HashMap _roles=new HashMap(7); |
| private SSORealm _ssoRealm; |
| |
| |
| /* ------------------------------------------------------------ */ |
| /** Constructor. |
| */ |
| public HashUserRealm() |
| {} |
| |
| /* ------------------------------------------------------------ */ |
| /** Constructor. |
| * @param name Realm Name |
| */ |
| public HashUserRealm(String name) |
| { |
| _realmName=name; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** Constructor. |
| * @param name Realm name |
| * @param config Filename or url of user properties file. |
| */ |
| public HashUserRealm(String name, String config) |
| throws IOException |
| { |
| _realmName=name; |
| load(config); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public void writeExternal(java.io.ObjectOutput out) |
| throws java.io.IOException |
| { |
| out.writeObject(_realmName); |
| out.writeObject(_config); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public void readExternal(java.io.ObjectInput in) |
| throws java.io.IOException, ClassNotFoundException |
| { |
| _realmName= (String)in.readObject(); |
| _config=(String)in.readObject(); |
| if (_config!=null) |
| load(_config); |
| } |
| |
| |
| /* ------------------------------------------------------------ */ |
| /** Load realm users from properties file. |
| * The property file maps usernames to password specs followed by |
| * an optional comma separated list of role names. |
| * |
| * @param config Filename or url of user properties file. |
| * @exception IOException |
| */ |
| public void load(String config) |
| throws IOException |
| { |
| _config=config; |
| if(log.isDebugEnabled())log.debug("Load "+this+" from "+config); |
| Properties properties = new Properties(); |
| Resource resource=Resource.newResource(config); |
| properties.load(resource.getInputStream()); |
| |
| Iterator iter = properties.entrySet().iterator(); |
| while(iter.hasNext()) |
| { |
| Map.Entry entry = (Map.Entry)iter.next(); |
| |
| String username=entry.getKey().toString().trim(); |
| String credentials=entry.getValue().toString().trim(); |
| String roles=null; |
| int c=credentials.indexOf(','); |
| if (c>0) |
| { |
| roles=credentials.substring(c+1).trim(); |
| credentials=credentials.substring(0,c).trim(); |
| } |
| |
| if (username!=null && username.length()>0 && |
| credentials!=null && credentials.length()>0) |
| { |
| put(username,credentials); |
| if(roles!=null && roles.length()>0) |
| { |
| StringTokenizer tok = new StringTokenizer(roles,", "); |
| while (tok.hasMoreTokens()) |
| addUserToRole(username,tok.nextToken()); |
| } |
| } |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @param name The realm name |
| */ |
| public void setName(String name) |
| { |
| _realmName=name; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @return The realm name. |
| */ |
| public String getName() |
| { |
| return _realmName; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public Principal getPrincipal(String username) |
| { |
| return (Principal)super.get(username); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public Principal authenticate(String username, |
| Object credentials, |
| HttpRequest request) |
| { |
| KnownUser user; |
| synchronized (this) |
| { |
| user = (KnownUser)super.get(username); |
| } |
| if (user==null) |
| return null; |
| |
| if (user.authenticate(credentials)) |
| return user; |
| |
| return null; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public void disassociate(Principal user) |
| { |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public Principal pushRole(Principal user, String role) |
| { |
| if (user==null) |
| user=new User(); |
| |
| return new WrappedUser(user,role); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public Principal popRole(Principal user) |
| { |
| WrappedUser wu = (WrappedUser)user; |
| return wu.getUserPrincipal(); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** Put user into realm. |
| * @param name User name |
| * @param credentials String password, Password or UserPrinciple |
| * instance. |
| * @return Old UserPrinciple value or null |
| */ |
| public synchronized Object put(Object name, Object credentials) |
| { |
| if (credentials instanceof Principal) |
| return super.put(name.toString(), |
| credentials); |
| |
| if (credentials instanceof Password) |
| return super.put(name, |
| new KnownUser(name.toString(), |
| (Password)credentials)); |
| if (credentials != null) |
| return super |
| .put(name, |
| new KnownUser(name.toString(), |
| Credential.getCredential(credentials.toString()))); |
| return null; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** Add a user to a role. |
| * @param userName |
| * @param roleName |
| */ |
| public synchronized void addUserToRole(String userName, String roleName) |
| { |
| HashSet userSet = (HashSet)_roles.get(roleName); |
| if (userSet==null) |
| { |
| userSet=new HashSet(11); |
| _roles.put(roleName,userSet); |
| } |
| userSet.add(userName); |
| } |
| |
| /* -------------------------------------------------------- */ |
| public boolean reauthenticate(Principal user) |
| { |
| return ((User)user).isAuthenticated(); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** Check if a user is in a role. |
| * @param user The user, which must be from this realm |
| * @param roleName |
| * @return True if the user can act in the role. |
| */ |
| public synchronized boolean isUserInRole(Principal user, String roleName) |
| { |
| if (user instanceof WrappedUser) |
| return ((WrappedUser)user).isUserInRole(roleName); |
| |
| if (user==null || ((User)user).getUserRealm()!=this) |
| return false; |
| |
| HashSet userSet = (HashSet)_roles.get(roleName); |
| return userSet!=null && userSet.contains(user.getName()); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public void logout(Principal user) |
| {} |
| |
| /* ------------------------------------------------------------ */ |
| public String toString() |
| { |
| return "Realm["+_realmName+"]"; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public void dump(PrintStream out) |
| { |
| out.println(this+":"); |
| out.println(super.toString()); |
| out.println(_roles); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @return The SSORealm to delegate single sign on requests to. |
| */ |
| public SSORealm getSSORealm() |
| { |
| return _ssoRealm; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** Set the SSORealm. |
| * A SSORealm implementation may be set to enable support for SSO. |
| * @param ssoRealm The SSORealm to delegate single sign on requests to. |
| */ |
| public void setSSORealm(SSORealm ssoRealm) |
| { |
| _ssoRealm = ssoRealm; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public Credential getSingleSignOn(HttpRequest request, |
| HttpResponse response) |
| { |
| if (_ssoRealm!=null) |
| return _ssoRealm.getSingleSignOn(request,response); |
| return null; |
| } |
| |
| |
| /* ------------------------------------------------------------ */ |
| public void setSingleSignOn(HttpRequest request, |
| HttpResponse response, |
| Principal principal, |
| Credential credential) |
| { |
| if (_ssoRealm!=null) |
| _ssoRealm.setSingleSignOn(request,response,principal,credential); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public void clearSingleSignOn(String username) |
| { |
| if (_ssoRealm!=null) |
| _ssoRealm.clearSingleSignOn(username); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /* ------------------------------------------------------------ */ |
| /* ------------------------------------------------------------ */ |
| private class User implements Principal |
| { |
| List roles=null; |
| |
| /* ------------------------------------------------------------ */ |
| private UserRealm getUserRealm() |
| { |
| return HashUserRealm.this; |
| } |
| |
| public String getName() |
| { |
| return "Anonymous"; |
| } |
| |
| public boolean isAuthenticated() |
| { |
| return false; |
| } |
| |
| public String toString() |
| { |
| return getName(); |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /* ------------------------------------------------------------ */ |
| /* ------------------------------------------------------------ */ |
| private class KnownUser extends User |
| { |
| private String _userName; |
| private Credential _cred; |
| |
| /* -------------------------------------------------------- */ |
| KnownUser(String name,Credential credential) |
| { |
| _userName=name; |
| _cred=credential; |
| } |
| |
| /* -------------------------------------------------------- */ |
| boolean authenticate(Object credentials) |
| { |
| return _cred!=null && _cred.check(credentials); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public String getName() |
| { |
| return _userName; |
| } |
| |
| /* -------------------------------------------------------- */ |
| public boolean isAuthenticated() |
| { |
| return true; |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /* ------------------------------------------------------------ */ |
| /* ------------------------------------------------------------ */ |
| private class WrappedUser extends User |
| { |
| private Principal user; |
| private String role; |
| |
| WrappedUser(Principal user, String role) |
| { |
| this.user=user; |
| this.role=role; |
| } |
| |
| Principal getUserPrincipal() |
| { |
| return user; |
| } |
| |
| public String getName() |
| { |
| return "role:"+role; |
| } |
| |
| public boolean isAuthenticated() |
| { |
| return true; |
| } |
| |
| public boolean isUserInRole(String role) |
| { |
| return this.role.equals(role); |
| } |
| } |
| } |