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     /**
186      * @see org.eclipse.jetty.security.LoginService#login(java.lang.String, java.lang.Object)
187      */
188     public UserIdentity login(String username, Object credentials)
189     {
190         UserIdentity user = _users.get(username);
191         
192         if (user==null)
193             user = loadUser(username);
194         
195         if (user!=null)
196         {
197             UserPrincipal principal = (UserPrincipal)user.getUserPrincipal();
198             if (principal.authenticate(credentials))
199                 return user;
200         }
201         return null;
202     }
203 
204     /* ------------------------------------------------------------ */
205     public void logout(UserIdentity user)
206     {
207         // TODO maybe clear cache?
208     }
209     
210     /* ------------------------------------------------------------ */
211     protected abstract UserIdentity loadUser(String username);
212     
213     /* ------------------------------------------------------------ */
214     protected abstract void loadUsers() throws IOException;
215 
216 
217     /* ------------------------------------------------------------ */
218     /* ------------------------------------------------------------ */
219     /* ------------------------------------------------------------ */
220     public interface UserPrincipal extends Principal
221     {
222         boolean authenticate(Object credentials);
223         public boolean isAuthenticated();
224     }
225     
226     /* ------------------------------------------------------------ */
227     /* ------------------------------------------------------------ */
228     /* ------------------------------------------------------------ */
229     public class RolePrincipal implements Principal
230     {
231         private final String _name;
232         public RolePrincipal(String name)
233         {
234             _name=name;
235         }
236         public String getName()
237         {
238             return _name;
239         }
240     }
241 
242     /* ------------------------------------------------------------ */
243     /* ------------------------------------------------------------ */
244     /* ------------------------------------------------------------ */
245     public static class Anonymous implements UserPrincipal
246     {
247         public boolean isAuthenticated()
248         {
249             return false;
250         }
251 
252         public String getName()
253         {
254             return "Anonymous";
255         }
256         
257         public boolean authenticate(Object credentials)
258         {
259             return false;
260         }
261         
262     }
263     
264     /* ------------------------------------------------------------ */
265     /* ------------------------------------------------------------ */
266     /* ------------------------------------------------------------ */
267     public static class KnownUser implements UserPrincipal
268     {
269         private final String _name;
270         private final Credential _credential;
271         
272         /* -------------------------------------------------------- */
273         public KnownUser(String name,Credential credential)
274         {
275             _name=name;
276             _credential=credential;
277         }
278 
279         /* -------------------------------------------------------- */
280         public boolean authenticate(Object credentials)
281         {
282             return _credential!=null && _credential.check(credentials);
283         }
284         
285         /* ------------------------------------------------------------ */
286         public String getName()
287         {
288             return _name;
289         }
290         
291         /* -------------------------------------------------------- */
292         public boolean isAuthenticated()
293         {
294             return true;
295         }
296 
297         /* -------------------------------------------------------- */
298         public String toString()
299         {
300             return _name;
301         }
302     }
303 }
304