View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.authc;
20  
21  import org.apache.shiro.authz.Permission;
22  import org.apache.shiro.authz.SimpleAuthorizationInfo;
23  import org.apache.shiro.subject.PrincipalCollection;
24  import org.apache.shiro.subject.SimplePrincipalCollection;
25  import org.apache.shiro.lang.util.ByteSource;
26  
27  import java.io.Serializable;
28  import java.util.Collection;
29  import java.util.Set;
30  
31  
32  /**
33   * Simple implementation of the {@link org.apache.shiro.authc.Account} interface that
34   * contains principal and credential and authorization information (roles and permissions) as instance variables and
35   * exposes them via getters and setters using standard JavaBean notation.
36   *
37   * @since 0.1
38   */
39  public class SimpleAccount implements Account, MergableAuthenticationInfo, SaltedAuthenticationInfo, Serializable {
40  
41      /*--------------------------------------------
42      |    I N S T A N C E   V A R I A B L E S    |
43      ============================================*/
44      /**
45       * The authentication information (principals and credentials) for this account.
46       */
47      private SimpleAuthenticationInfo authcInfo;
48  
49      /**
50       * The authorization information for this account.
51       */
52      private SimpleAuthorizationInfo authzInfo;
53  
54      /**
55       * Indicates this account is locked.  This isn't honored by all <tt>Realms</tt> but is honored by
56       * {@link org.apache.shiro.realm.SimpleAccountRealm}.
57       */
58      private boolean locked;
59  
60      /**
61       * Indicates credentials on this account are expired.  This isn't honored by all <tt>Realms</tt> but is honored by
62       * {@link org.apache.shiro.realm.SimpleAccountRealm}.
63       */
64      private boolean credentialsExpired;
65  
66      /*--------------------------------------------
67      |         C O N S T R U C T O R S           |
68      ============================================*/
69  
70      /**
71       * Default no-argument constructor.
72       */
73      public SimpleAccount() {
74      }
75  
76      /**
77       * Constructs a SimpleAccount instance for the specified realm with the given principals and credentials.
78       *
79       * @param principal   the 'primary' identifying attribute of the account, for example, a user id or username.
80       * @param credentials the credentials that verify identity for the account
81       * @param realmName   the name of the realm that accesses this account data
82       */
83      public SimpleAccount(Object principal, Object credentials, String realmName) {
84          this(principal instanceof PrincipalCollection
85                  ? (PrincipalCollection) principal : new SimplePrincipalCollection(principal, realmName), credentials);
86      }
87  
88      /**
89       * Constructs a SimpleAccount instance for the specified realm with the given principals, hashedCredentials and
90       * credentials salt used when hashing the credentials.
91       *
92       * @param principal         the 'primary' identifying attribute of the account, for example, a user id or username.
93       * @param hashedCredentials the credentials that verify identity for the account
94       * @param credentialsSalt   the salt used when hashing the credentials
95       * @param realmName         the name of the realm that accesses this account data
96       * @see org.apache.shiro.authc.credential.HashedCredentialsMatcher HashedCredentialsMatcher
97       * @since 1.1
98       */
99      public SimpleAccount(Object principal, Object hashedCredentials, ByteSource credentialsSalt, String realmName) {
100         this(principal instanceof PrincipalCollection ? (PrincipalCollection) principal
101                         : new SimplePrincipalCollection(principal, realmName),
102                 hashedCredentials, credentialsSalt);
103     }
104 
105     /**
106      * Constructs a SimpleAccount instance for the specified realm with the given principals and credentials.
107      *
108      * @param principals  the identifying attributes of the account, at least one of which should be considered the
109      *                    account's 'primary' identifying attribute, for example, a user id or username.
110      * @param credentials the credentials that verify identity for the account
111      * @param realmName   the name of the realm that accesses this account data
112      */
113     public SimpleAccount(Collection principals, Object credentials, String realmName) {
114         this(new SimplePrincipalCollection(principals, realmName), credentials);
115     }
116 
117     /**
118      * Constructs a SimpleAccount instance for the specified principals and credentials.
119      *
120      * @param principals  the identifying attributes of the account, at least one of which should be considered the
121      *                    account's 'primary' identifying attribute, for example, a user id or username.
122      * @param credentials the credentials that verify identity for the account
123      */
124     public SimpleAccount(PrincipalCollection principals, Object credentials) {
125         this.authcInfo = new SimpleAuthenticationInfo(principals, credentials);
126         this.authzInfo = new SimpleAuthorizationInfo();
127     }
128 
129     /**
130      * Constructs a SimpleAccount instance for the specified principals and credentials.
131      *
132      * @param principals        the identifying attributes of the account, at least one of which should be considered the
133      *                          account's 'primary' identifying attribute, for example, a user id or username.
134      * @param hashedCredentials the hashed credentials that verify identity for the account
135      * @param credentialsSalt   the salt used when hashing the credentials
136      * @see org.apache.shiro.authc.credential.HashedCredentialsMatcher HashedCredentialsMatcher
137      * @since 1.1
138      */
139     public SimpleAccount(PrincipalCollection principals, Object hashedCredentials, ByteSource credentialsSalt) {
140         this.authcInfo = new SimpleAuthenticationInfo(principals, hashedCredentials, credentialsSalt);
141         this.authzInfo = new SimpleAuthorizationInfo();
142     }
143 
144     /**
145      * Constructs a SimpleAccount instance for the specified principals and credentials, with the assigned roles.
146      *
147      * @param principals  the identifying attributes of the account, at least one of which should be considered the
148      *                    account's 'primary' identifying attribute, for example, a user id or username.
149      * @param credentials the credentials that verify identity for the account
150      * @param roles       the names of the roles assigned to this account.
151      */
152     public SimpleAccount(PrincipalCollection principals, Object credentials, Set<String> roles) {
153         this.authcInfo = new SimpleAuthenticationInfo(principals, credentials);
154         this.authzInfo = new SimpleAuthorizationInfo(roles);
155     }
156 
157     /**
158      * Constructs a SimpleAccount instance for the specified realm with the given principal and credentials, with the
159      * the assigned roles and permissions.
160      *
161      * @param principal   the 'primary' identifying attributes of the account, for example, a user id or username.
162      * @param credentials the credentials that verify identity for the account
163      * @param realmName   the name of the realm that accesses this account data
164      * @param roleNames   the names of the roles assigned to this account.
165      * @param permissions the permissions assigned to this account directly (not those assigned to any of the realms).
166      */
167     public SimpleAccount(Object principal, Object credentials, String realmName,
168                          Set<String> roleNames, Set<Permission> permissions) {
169         this.authcInfo = new SimpleAuthenticationInfo(new SimplePrincipalCollection(principal, realmName), credentials);
170         this.authzInfo = new SimpleAuthorizationInfo(roleNames);
171         this.authzInfo.setObjectPermissions(permissions);
172     }
173 
174     /**
175      * Constructs a SimpleAccount instance for the specified realm with the given principals and credentials, with the
176      * the assigned roles and permissions.
177      *
178      * @param principals  the identifying attributes of the account, at least one of which should be considered the
179      *                    account's 'primary' identifying attribute, for example, a user id or username.
180      * @param credentials the credentials that verify identity for the account
181      * @param realmName   the name of the realm that accesses this account data
182      * @param roleNames   the names of the roles assigned to this account.
183      * @param permissions the permissions assigned to this account directly (not those assigned to any of the realms).
184      */
185 
186     public SimpleAccount(Collection principals, Object credentials, String realmName,
187                          Set<String> roleNames, Set<Permission> permissions) {
188         this.authcInfo = new SimpleAuthenticationInfo(new SimplePrincipalCollection(principals, realmName), credentials);
189         this.authzInfo = new SimpleAuthorizationInfo(roleNames);
190         this.authzInfo.setObjectPermissions(permissions);
191     }
192 
193     /**
194      * Constructs a SimpleAccount instance from the given principals and credentials, with the
195      * the assigned roles and permissions.
196      *
197      * @param principals  the identifying attributes of the account, at least one of which should be considered the
198      *                    account's 'primary' identifying attribute, for example, a user id or username.
199      * @param credentials the credentials that verify identity for the account
200      * @param roleNames   the names of the roles assigned to this account.
201      * @param permissions the permissions assigned to this account directly (not those assigned to any of the realms).
202      */
203     public SimpleAccount(PrincipalCollection principals, Object credentials, Set<String> roleNames, Set<Permission> permissions) {
204         this.authcInfo = new SimpleAuthenticationInfo(principals, credentials);
205         this.authzInfo = new SimpleAuthorizationInfo(roleNames);
206         this.authzInfo.setObjectPermissions(permissions);
207     }
208 
209     /*--------------------------------------------
210     |  A C C E S S O R S / M O D I F I E R S    |
211     ============================================*/
212 
213     /**
214      * Returns the principals, aka the identifying attributes (username, user id, first name, last name, etc.) of this
215      * Account.
216      *
217      * @return all the principals, aka the identifying attributes, of this Account.
218      */
219     public PrincipalCollection getPrincipals() {
220         return authcInfo.getPrincipals();
221     }
222 
223     /**
224      * Sets the principals, aka the identifying attributes (username, user id, first name, last name, etc.) of this
225      * Account.
226      *
227      * @param principals all the principals, aka the identifying attributes, of this Account.
228      * @see Account#getPrincipals()
229      */
230     public void setPrincipals(PrincipalCollection principals) {
231         this.authcInfo.setPrincipals(principals);
232     }
233 
234 
235     /**
236      * Simply returns <code>this.authcInfo.getCredentials</code>.  The <code>authcInfo</code> attribute is constructed
237      * via the constructors to wrap the input arguments.
238      *
239      * @return this Account's credentials.
240      */
241     public Object getCredentials() {
242         return authcInfo.getCredentials();
243     }
244 
245     /**
246      * Sets this Account's credentials that verify one or more of the Account's
247      * {@link #getPrincipals() principals}, such as a password or private key.
248      *
249      * @param credentials the credentials associated with this Account that verify one or more of the Account principals.
250      * @see org.apache.shiro.authc.Account#getCredentials()
251      */
252     public void setCredentials(Object credentials) {
253         this.authcInfo.setCredentials(credentials);
254     }
255 
256     /**
257      * Returns the salt used to hash this Account's credentials (e.g. for password hashing), or {@code null} if no salt
258      * was used or credentials were not hashed at all.
259      *
260      * @return the salt used to hash this Account's credentials (e.g. for password hashing), or {@code null} if no salt
261      * was used or credentials were not hashed at all.
262      * @since 1.1
263      */
264     public ByteSource getCredentialsSalt() {
265         return this.authcInfo.getCredentialsSalt();
266     }
267 
268     /**
269      * Sets the salt to use to hash this Account's credentials (e.g. for password hashing), or {@code null} if no salt
270      * is used or credentials are not hashed at all.
271      *
272      * @param salt the salt to use to hash this Account's credentials (e.g. for password hashing), or {@code null} if no
273      *             salt is used or credentials are not hashed at all.
274      * @since 1.1
275      */
276     public void setCredentialsSalt(ByteSource salt) {
277         this.authcInfo.setCredentialsSalt(salt);
278     }
279 
280     /**
281      * Returns <code>this.authzInfo.getRoles();</code>
282      *
283      * @return the Account's assigned roles.
284      */
285     public Collection<String> getRoles() {
286         return authzInfo.getRoles();
287     }
288 
289     /**
290      * Sets the Account's assigned roles.  Simply calls <code>this.authzInfo.setRoles(roles)</code>.
291      *
292      * @param roles the Account's assigned roles.
293      * @see Account#getRoles()
294      */
295     public void setRoles(Set<String> roles) {
296         this.authzInfo.setRoles(roles);
297     }
298 
299     /**
300      * Adds a role to this Account's set of assigned roles.  Simply delegates to
301      * <code>this.authzInfo.addRole(role)</code>.
302      *
303      * @param role a role to assign to this Account.
304      */
305     public void addRole(String role) {
306         this.authzInfo.addRole(role);
307     }
308 
309     /**
310      * Adds one or more roles to this Account's set of assigned roles. Simply delegates to
311      * <code>this.authzInfo.addRoles(roles)</code>.
312      *
313      * @param roles one or more roles to assign to this Account.
314      */
315     public void addRole(Collection<String> roles) {
316         this.authzInfo.addRoles(roles);
317     }
318 
319     /**
320      * Returns all String-based permissions assigned to this Account.  Simply delegates to
321      * <code>this.authzInfo.getStringPermissions()</code>.
322      *
323      * @return all String-based permissions assigned to this Account.
324      */
325     public Collection<String> getStringPermissions() {
326         return authzInfo.getStringPermissions();
327     }
328 
329     /**
330      * Sets the String-based permissions assigned to this Account.  Simply delegates to
331      * <code>this.authzInfo.setStringPermissions(permissions)</code>.
332      *
333      * @param permissions all String-based permissions assigned to this Account.
334      * @see org.apache.shiro.authc.Account#getStringPermissions()
335      */
336     public void setStringPermissions(Set<String> permissions) {
337         this.authzInfo.setStringPermissions(permissions);
338     }
339 
340     /**
341      * Assigns a String-based permission directly to this Account (not to any of its realms).
342      *
343      * @param permission the String-based permission to assign.
344      */
345     public void addStringPermission(String permission) {
346         this.authzInfo.addStringPermission(permission);
347     }
348 
349     /**
350      * Assigns one or more string-based permissions directly to this Account (not to any of its realms).
351      *
352      * @param permissions one or more String-based permissions to assign.
353      */
354     public void addStringPermissions(Collection<String> permissions) {
355         this.authzInfo.addStringPermissions(permissions);
356     }
357 
358     /**
359      * Returns all object-based permissions assigned directly to this Account (not any of its realms).
360      *
361      * @return all object-based permissions assigned directly to this Account (not any of its realms).
362      */
363     public Collection<Permission> getObjectPermissions() {
364         return authzInfo.getObjectPermissions();
365     }
366 
367     /**
368      * Set al. object-based permissions assigned directly to this Account (not any of its realms).
369      *
370      * @param permissions the object-based permissions to assign directly to this Account.
371      */
372     public void setObjectPermissions(Set<Permission> permissions) {
373         this.authzInfo.setObjectPermissions(permissions);
374     }
375 
376     /**
377      * Assigns an object-based permission directly to this Account (not any of its realms).
378      *
379      * @param permission the object-based permission to assign directly to this Account (not any of its realms).
380      */
381     public void addObjectPermission(Permission permission) {
382         this.authzInfo.addObjectPermission(permission);
383     }
384 
385     /**
386      * Assigns one or more object-based permissions directly to this Account (not any of its realms).
387      *
388      * @param permissions one or more object-based permissions to assign directly to this Account (not any of its realms).
389      */
390     public void addObjectPermissions(Collection<Permission> permissions) {
391         this.authzInfo.addObjectPermissions(permissions);
392     }
393 
394     /**
395      * Returns <code>true</code> if this Account is locked and thus cannot be used to login, <code>false</code> otherwise.
396      *
397      * @return <code>true</code> if this Account is locked and thus cannot be used to login, <code>false</code> otherwise.
398      */
399     public boolean isLocked() {
400         return locked;
401     }
402 
403     /**
404      * Sets whether or not the account is locked and can be used to login.
405      *
406      * @param locked <code>true</code> if this Account is locked and thus cannot be used to login, <code>false</code> otherwise.
407      */
408     public void setLocked(boolean locked) {
409         this.locked = locked;
410     }
411 
412     /**
413      * Returns whether or not the Account's credentials are expired.  This usually indicates that the Subject or an application
414      * administrator would need to change the credentials before the account could be used.
415      *
416      * @return whether or not the Account's credentials are expired.
417      */
418     public boolean isCredentialsExpired() {
419         return credentialsExpired;
420     }
421 
422     /**
423      * Sets whether or not the Account's credentials are expired.  A <code>true</code> value indicates that the Subject
424      * or application administrator would need to change their credentials before the account could be used.
425      *
426      * @param credentialsExpired <code>true</code> if this Account's credentials are expired and need to be changed,
427      *                           <code>false</code> otherwise.
428      */
429     public void setCredentialsExpired(boolean credentialsExpired) {
430         this.credentialsExpired = credentialsExpired;
431     }
432 
433 
434     /**
435      * Merges the specified <code>AuthenticationInfo</code> into this <code>Account</code>.
436      * <p/>
437      * If the specified argument is also an instance of {@link SimpleAccount SimpleAccount}, the
438      * {@link #isLocked()} and {@link #isCredentialsExpired()} attributes are merged (set on this instance) as well
439      * (only if their values are <code>true</code>).
440      *
441      * @param info the <code>AuthenticationInfo</code> to merge into this account.
442      */
443     public void merge(AuthenticationInfo info) {
444         authcInfo.merge(info);
445 
446         // Merge SimpleAccount specific info
447         if (info instanceof SimpleAccount) {
448             SimpleAccount otherAccount = (SimpleAccount) info;
449             if (otherAccount.isLocked()) {
450                 setLocked(true);
451             }
452 
453             if (otherAccount.isCredentialsExpired()) {
454                 setCredentialsExpired(true);
455             }
456         }
457     }
458 
459     /**
460      * If the {@link #getPrincipals() principals} are not null, returns <code>principals.hashCode()</code>, otherwise
461      * returns 0 (zero).
462      *
463      * @return <code>principals.hashCode()</code> if they are not null, 0 (zero) otherwise.
464      */
465     public int hashCode() {
466         return (getPrincipals() != null ? getPrincipals().hashCode() : 0);
467     }
468 
469     /**
470      * Returns <code>true</code> if the specified object is also a {@link SimpleAccount SimpleAccount} and its
471      * {@link #getPrincipals() principals} are equal to this object's <code>principals</code>, <code>false</code> otherwise.
472      *
473      * @param o the object to test for equality.
474      * @return <code>true</code> if the specified object is also a {@link SimpleAccount SimpleAccount} and its
475      * {@link #getPrincipals() principals} are equal to this object's <code>principals</code>, <code>false</code> otherwise.
476      */
477     public boolean equals(Object o) {
478         if (o == this) {
479             return true;
480         }
481         if (o instanceof SimpleAccount) {
482             SimpleAccount sa = (SimpleAccount) o;
483             //principal should be unique across the application, so only check this for equality:
484             return (getPrincipals() != null ? getPrincipals().equals(sa.getPrincipals()) : sa.getPrincipals() == null);
485         }
486         return false;
487     }
488 
489     /**
490      * Returns {@link #getPrincipals() principals}.toString() if they are not null, otherwise prints out the string
491      * &quot;empty&quot;
492      *
493      * @return the String representation of this Account object.
494      */
495     public String toString() {
496         return getPrincipals() != null ? getPrincipals().toString() : "empty";
497     }
498 
499 }