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