View Javadoc

1   // ========================================================================
2   // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  
14  
15  package org.eclipse.jetty.security;
16  
17  import java.io.IOException;
18  import java.io.Serializable;
19  import java.security.Principal;
20  import java.util.Map;
21  import java.util.concurrent.ConcurrentHashMap;
22  import java.util.concurrent.ConcurrentMap;
23  
24  import javax.security.auth.Subject;
25  
26  import org.eclipse.jetty.http.security.Credential;
27  import org.eclipse.jetty.server.UserIdentity;
28  import org.eclipse.jetty.util.component.AbstractLifeCycle;
29  import org.eclipse.jetty.util.log.Log;
30  
31  
32  
33  /* ------------------------------------------------------------ */
34  /**
35   * A login service that keeps UserIdentities in a concurrent map
36   * either as the source or a cache of the users.
37   * 
38   */
39  public abstract class MappedLoginService extends AbstractLifeCycle implements LoginService
40  {
41      protected IdentityService _identityService=new DefaultIdentityService();
42      protected String _name;
43      protected final ConcurrentMap<String, UserIdentity> _users=new ConcurrentHashMap<String, UserIdentity>();
44  
45      /* ------------------------------------------------------------ */
46      protected MappedLoginService()
47      {
48      }
49      
50      /* ------------------------------------------------------------ */
51      /** Get the name.
52       * @return the name
53       */
54      public String getName()
55      {
56          return _name;
57      }
58      
59      /* ------------------------------------------------------------ */
60      /** Get the identityService.
61       * @return the identityService
62       */
63      public IdentityService getIdentityService()
64      {
65          return _identityService;
66      }
67      
68      /* ------------------------------------------------------------ */
69      /** Get the users.
70       * @return the users
71       */
72      public ConcurrentMap<String, UserIdentity> getUsers()
73      {
74          return _users;
75      }
76      
77      /* ------------------------------------------------------------ */
78      /** Set the identityService.
79       * @param identityService the identityService to set
80       */
81      public void setIdentityService(IdentityService identityService)
82      {
83          if (isRunning())
84              throw new IllegalStateException("Running");
85          _identityService = identityService;
86      }
87  
88      /* ------------------------------------------------------------ */
89      /** Set the name.
90       * @param name the name to set
91       */
92      public void setName(String name)
93      {
94          if (isRunning())
95              throw new IllegalStateException("Running");
96          _name = name;
97      }
98  
99      /* ------------------------------------------------------------ */
100     /** Set the users.
101      * @param users the users to set
102      */
103     public void setUsers(Map<String, UserIdentity> users)
104     {
105         if (isRunning())
106             throw new IllegalStateException("Running");
107         _users.clear();
108         _users.putAll(users);
109     }
110 
111     /* ------------------------------------------------------------ */
112     /**
113      * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
114      */
115     @Override
116     protected void doStart() throws Exception
117     {
118         loadUsers();
119         super.doStart();
120     }
121 
122     /* ------------------------------------------------------------ */
123     @Override
124     protected void doStop() throws Exception
125     {
126         super.doStop();
127     }
128 
129     /* ------------------------------------------------------------ */
130     public void logout(UserIdentity identity)
131     {   
132         Log.debug("logout {}",identity);
133     }
134     
135     /* ------------------------------------------------------------ */
136     @Override
137     public String toString()
138     {
139         return this.getClass().getSimpleName()+"["+_name+"]";
140     }
141     
142     /* ------------------------------------------------------------ */
143     /** Put user into realm.
144      * Called by implementations to put the user data loaded from
145      * file/db etc into the user structure.
146      * @param userName User name
147      * @param info a UserIdentity instance, or a String password or Credential instance
148      * @return User instance
149      */
150     protected synchronized UserIdentity putUser(String userName, Object info)
151     {
152         final UserIdentity identity;
153         if (info instanceof UserIdentity)
154             identity=(UserIdentity)info;
155         else
156         {
157             Credential credential = (info instanceof Credential)?(Credential)info:Credential.getCredential(info.toString());
158             
159             Principal userPrincipal = new KnownUser(userName,credential);
160             Subject subject = new Subject();
161             subject.getPrincipals().add(userPrincipal);
162             subject.getPrivateCredentials().add(credential);
163             subject.setReadOnly();
164             identity=_identityService.newUserIdentity(subject,userPrincipal,IdentityService.NO_ROLES);
165         }
166         
167         _users.put(userName,identity);
168         return identity;
169     }
170     
171     /* ------------------------------------------------------------ */
172     /** Put user into realm.
173      * @param userName The user to add
174      * @param credential The users Credentials
175      * @param roles The users roles
176      * @return UserIdentity
177      */
178     public synchronized UserIdentity putUser(String userName, Credential credential, String[] roles)
179     {
180         Principal userPrincipal = new KnownUser(userName,credential);
181         Subject subject = new Subject();
182         subject.getPrincipals().add(userPrincipal);
183         subject.getPrivateCredentials().add(credential);
184         
185         if (roles!=null)
186             for (String role : roles)
187                 subject.getPrincipals().add(new RolePrincipal(role));
188 
189         subject.setReadOnly();
190         UserIdentity identity=_identityService.newUserIdentity(subject,userPrincipal,roles);
191         _users.put(userName,identity);
192         return identity;
193     } 
194     
195     /* ------------------------------------------------------------ */
196     public void removeUser(String username)
197     {
198         _users.remove(username);
199     }   
200 
201     /* ------------------------------------------------------------ */
202     /**
203      * @see org.eclipse.jetty.security.LoginService#login(java.lang.String, java.lang.Object)
204      */
205     public UserIdentity login(String username, Object credentials)
206     {
207         UserIdentity user = _users.get(username);
208         
209         if (user==null)
210             user = loadUser(username);
211         
212         if (user!=null)
213         {
214             UserPrincipal principal = (UserPrincipal)user.getUserPrincipal();
215             if (principal.authenticate(credentials))
216                 return user;
217         }
218         return null;
219     }
220 
221     /* ------------------------------------------------------------ */
222     public boolean validate(UserIdentity user)
223     {
224         if (_users.containsKey(user.getUserPrincipal().getName()))
225             return true;
226         
227         if (loadUser(user.getUserPrincipal().getName())!=null)
228             return true;
229                 
230         return false;
231     }
232 
233     /* ------------------------------------------------------------ */
234     protected abstract UserIdentity loadUser(String username);
235     
236     /* ------------------------------------------------------------ */
237     protected abstract void loadUsers() throws IOException;
238 
239 
240     /* ------------------------------------------------------------ */
241     /* ------------------------------------------------------------ */
242     /* ------------------------------------------------------------ */
243     public interface UserPrincipal extends Principal,Serializable
244     {
245         boolean authenticate(Object credentials);
246         public boolean isAuthenticated();
247     }
248     
249     /* ------------------------------------------------------------ */
250     /* ------------------------------------------------------------ */
251     /* ------------------------------------------------------------ */
252     public static class RolePrincipal implements Principal,Serializable
253     {
254         private static final long serialVersionUID = 2998397924051854402L;
255         private final String _roleName;
256         public RolePrincipal(String name)
257         {
258             _roleName=name;
259         }
260         public String getName()
261         {
262             return _roleName;
263         }
264     }
265 
266     /* ------------------------------------------------------------ */
267     /* ------------------------------------------------------------ */
268     /* ------------------------------------------------------------ */
269     public static class Anonymous implements UserPrincipal,Serializable
270     {
271         private static final long serialVersionUID = 1097640442553284845L;
272 
273         public boolean isAuthenticated()
274         {
275             return false;
276         }
277 
278         public String getName()
279         {
280             return "Anonymous";
281         }
282         
283         public boolean authenticate(Object credentials)
284         {
285             return false;
286         }
287         
288     }
289     
290     /* ------------------------------------------------------------ */
291     /* ------------------------------------------------------------ */
292     /* ------------------------------------------------------------ */
293     public static class KnownUser implements UserPrincipal,Serializable
294     {
295         private static final long serialVersionUID = -6226920753748399662L;
296         private final String _name;
297         private final Credential _credential;
298         
299         /* -------------------------------------------------------- */
300         public KnownUser(String name,Credential credential)
301         {
302             _name=name;
303             _credential=credential;
304         }
305 
306         /* -------------------------------------------------------- */
307         public boolean authenticate(Object credentials)
308         {
309             return _credential!=null && _credential.check(credentials);
310         }
311         
312         /* ------------------------------------------------------------ */
313         public String getName()
314         {
315             return _name;
316         }
317         
318         /* -------------------------------------------------------- */
319         public boolean isAuthenticated()
320         {
321             return true;
322         }
323 
324         /* -------------------------------------------------------- */
325         @Override
326         public String toString()
327         {
328             return _name;
329         }
330     }
331 }
332