View Javadoc

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 }