1 // 2 // ======================================================================== 3 // Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd. 4 // ------------------------------------------------------------------------ 5 // All rights reserved. This program and the accompanying materials 6 // are made available under the terms of the Eclipse Public License v1.0 7 // and Apache License v2.0 which accompanies this distribution. 8 // 9 // The Eclipse Public License is available at 10 // http://www.eclipse.org/legal/epl-v10.html 11 // 12 // The Apache License v2.0 is available at 13 // http://www.opensource.org/licenses/apache2.0.php 14 // 15 // You may elect to redistribute this code under either of these licenses. 16 // ======================================================================== 17 // 18 19 package org.eclipse.jetty.security; 20 21 import java.io.IOException; 22 23 import org.eclipse.jetty.security.PropertyUserStore.UserListener; 24 import org.eclipse.jetty.server.UserIdentity; 25 import org.eclipse.jetty.util.Scanner; 26 import org.eclipse.jetty.util.log.Log; 27 import org.eclipse.jetty.util.log.Logger; 28 import org.eclipse.jetty.util.resource.Resource; 29 import org.eclipse.jetty.util.security.Credential; 30 31 /* ------------------------------------------------------------ */ 32 /** 33 * Properties User Realm. 34 * <p> 35 * An implementation of UserRealm that stores users and roles in-memory in HashMaps. 36 * <p> 37 * 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: 38 * 39 * <pre> 40 * username: password [,rolename ...] 41 * </pre> 42 * 43 * Passwords may be clear text, obfuscated or checksummed. The class com.eclipse.Util.Password should be used to generate obfuscated passwords or password 44 * checksums. 45 * <p> 46 * If DIGEST Authentication is used, the password must be in a recoverable format, either plain text or OBF:. 47 */ 48 public class HashLoginService extends MappedLoginService implements UserListener 49 { 50 private static final Logger LOG = Log.getLogger(HashLoginService.class); 51 52 private PropertyUserStore _propertyUserStore; 53 private String _config; 54 private Resource _configResource; 55 private Scanner _scanner; 56 private boolean hotReload = false; // default is not to reload 57 58 /* ------------------------------------------------------------ */ 59 public HashLoginService() 60 { 61 } 62 63 /* ------------------------------------------------------------ */ 64 public HashLoginService(String name) 65 { 66 setName(name); 67 } 68 69 /* ------------------------------------------------------------ */ 70 public HashLoginService(String name, String config) 71 { 72 setName(name); 73 setConfig(config); 74 } 75 76 /* ------------------------------------------------------------ */ 77 public String getConfig() 78 { 79 return _config; 80 } 81 82 /* ------------------------------------------------------------ */ 83 public void getConfig(String config) 84 { 85 _config = config; 86 } 87 88 /* ------------------------------------------------------------ */ 89 public Resource getConfigResource() 90 { 91 return _configResource; 92 } 93 94 /* ------------------------------------------------------------ */ 95 /** 96 * Load realm users from properties file. The property file maps usernames to password specs followed by an optional comma separated list of role names. 97 * 98 * @param config 99 * Filename or url of user properties file. 100 */ 101 public void setConfig(String config) 102 { 103 _config = config; 104 } 105 106 /** 107 * Is hot reload enabled on this user store 108 * 109 * @return true if hot reload was enabled before startup 110 */ 111 public boolean isHotReload() 112 { 113 return hotReload; 114 } 115 116 /** 117 * Enable Hot Reload of the Property File 118 * 119 * @param enable true to enable, false to disable 120 */ 121 public void setHotReload(boolean enable) 122 { 123 if (isRunning()) 124 { 125 throw new IllegalStateException("Cannot set hot reload while user store is running"); 126 } 127 this.hotReload = enable; 128 } 129 130 /* ------------------------------------------------------------ */ 131 /** 132 * sets the refresh interval (in seconds) 133 * @param sec the refresh interval 134 * @deprecated use {@link #setHotReload(boolean)} instead 135 */ 136 @Deprecated 137 public void setRefreshInterval(int sec) 138 { 139 } 140 141 /* ------------------------------------------------------------ */ 142 /** 143 * @return refresh interval in seconds for how often the properties file should be checked for changes 144 * @deprecated use {@link #isHotReload()} instead 145 */ 146 @Deprecated 147 public int getRefreshInterval() 148 { 149 return (hotReload)?1:0; 150 } 151 152 /* ------------------------------------------------------------ */ 153 @Override 154 protected UserIdentity loadUser(String username) 155 { 156 return null; 157 } 158 159 /* ------------------------------------------------------------ */ 160 @Override 161 public void loadUsers() throws IOException 162 { 163 // TODO: Consider refactoring MappedLoginService to not have to override with unused methods 164 } 165 166 /* ------------------------------------------------------------ */ 167 /** 168 * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart() 169 */ 170 @Override 171 protected void doStart() throws Exception 172 { 173 super.doStart(); 174 175 if (_propertyUserStore == null) 176 { 177 if(LOG.isDebugEnabled()) 178 LOG.debug("doStart: Starting new PropertyUserStore. PropertiesFile: " + _config + " hotReload: " + hotReload); 179 180 _propertyUserStore = new PropertyUserStore(); 181 _propertyUserStore.setHotReload(hotReload); 182 _propertyUserStore.setConfigPath(_config); 183 _propertyUserStore.registerUserListener(this); 184 _propertyUserStore.start(); 185 } 186 } 187 188 /* ------------------------------------------------------------ */ 189 /** 190 * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop() 191 */ 192 @Override 193 protected void doStop() throws Exception 194 { 195 super.doStop(); 196 if (_scanner != null) 197 _scanner.stop(); 198 _scanner = null; 199 } 200 201 /* ------------------------------------------------------------ */ 202 @Override 203 public void update(String userName, Credential credential, String[] roleArray) 204 { 205 if (LOG.isDebugEnabled()) 206 LOG.debug("update: " + userName + " Roles: " + roleArray.length); 207 putUser(userName,credential,roleArray); 208 } 209 210 /* ------------------------------------------------------------ */ 211 @Override 212 public void remove(String userName) 213 { 214 if (LOG.isDebugEnabled()) 215 LOG.debug("remove: " + userName); 216 removeUser(userName); 217 } 218 }