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.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 ? (PrincipalCollection) principal : new SimplePrincipalCollection(principal, realmName), credentials);
85      }
86  
87      /**
88       * Constructs a SimpleAccount instance for the specified realm with the given principals, hashedCredentials and
89       * credentials salt used when hashing the credentials.
90       *
91       * @param principal         the 'primary' identifying attribute of the account, for example, a user id or username.
92       * @param hashedCredentials the credentials that verify identity for the account
93       * @param credentialsSalt   the salt used when hashing the credentials
94       * @param realmName         the name of the realm that accesses this account data
95       * @see org.apache.shiro.authc.credential.HashedCredentialsMatcher HashedCredentialsMatcher
96       * @since 1.1
97       */
98      public SimpleAccount(Object principal, Object hashedCredentials, ByteSource credentialsSalt, String realmName) {
99          this(principal instanceof PrincipalCollection ? (PrincipalCollection) principal : new SimplePrincipalCollection(principal, realmName),
100                 hashedCredentials, credentialsSalt);
101     }
102 
103     /**
104      * Constructs a SimpleAccount instance for the specified realm with the given principals and credentials.
105      *
106      * @param principals  the identifying attributes of the account, at least one of which should be considered the
107      *                    account's 'primary' identifying attribute, for example, a user id or username.
108      * @param credentials the credentials that verify identity for the account
109      * @param realmName   the name of the realm that accesses this account data
110      */
111     public SimpleAccount(Collection principals, Object credentials, String realmName) {
112         this(new SimplePrincipalCollection(principals, realmName), credentials);
113     }
114 
115     /**
116      * Constructs a SimpleAccount instance for the specified principals and credentials.
117      *
118      * @param principals  the identifying attributes of the account, at least one of which should be considered the
119      *                    account's 'primary' identifying attribute, for example, a user id or username.
120      * @param credentials the credentials that verify identity for the account
121      */
122     public SimpleAccount(PrincipalCollection principals, Object credentials) {
123         this.authcInfo = new SimpleAuthenticationInfo(principals, credentials);
124         this.authzInfo = new SimpleAuthorizationInfo();
125     }
126 
127     /**
128      * Constructs a SimpleAccount instance for the specified principals and credentials.
129      *
130      * @param principals        the identifying attributes of the account, at least one of which should be considered the
131      *                          account's 'primary' identifying attribute, for example, a user id or username.
132      * @param hashedCredentials the hashed credentials that verify identity for the account
133      * @param credentialsSalt   the salt used when hashing the credentials
134      * @see org.apache.shiro.authc.credential.HashedCredentialsMatcher HashedCredentialsMatcher
135      * @since 1.1
136      */
137     public SimpleAccount(PrincipalCollection principals, Object hashedCredentials, ByteSource credentialsSalt) {
138         this.authcInfo = new SimpleAuthenticationInfo(principals, hashedCredentials, credentialsSalt);
139         this.authzInfo = new SimpleAuthorizationInfo();
140     }
141 
142     /**
143      * Constructs a SimpleAccount instance for the specified principals and credentials, with the assigned roles.
144      *
145      * @param principals  the identifying attributes of the account, at least one of which should be considered the
146      *                    account's 'primary' identifying attribute, for example, a user id or username.
147      * @param credentials the credentials that verify identity for the account
148      * @param roles       the names of the roles assigned to this account.
149      */
150     public SimpleAccount(PrincipalCollection principals, Object credentials, Set<String> roles) {
151         this.authcInfo = new SimpleAuthenticationInfo(principals, credentials);
152         this.authzInfo = new SimpleAuthorizationInfo(roles);
153     }
154 
155     /**
156      * Constructs a SimpleAccount instance for the specified realm with the given principal and credentials, with the
157      * the assigned roles and permissions.
158      *
159      * @param principal   the 'primary' identifying attributes of the account, for example, a user id or username.
160      * @param credentials the credentials that verify identity for the account
161      * @param realmName   the name of the realm that accesses this account data
162      * @param roleNames   the names of the roles assigned to this account.
163      * @param permissions the permissions assigned to this account directly (not those assigned to any of the realms).
164      */
165     public SimpleAccount(Object principal, Object credentials, String realmName, Set<String> roleNames, Set<Permission> permissions) {
166         this.authcInfo = new SimpleAuthenticationInfo(new SimplePrincipalCollection(principal, realmName), credentials);
167         this.authzInfo = new SimpleAuthorizationInfo(roleNames);
168         this.authzInfo.setObjectPermissions(permissions);
169     }
170 
171     /**
172      * Constructs a SimpleAccount instance for the specified realm with the given principals and credentials, with the
173      * the assigned roles and permissions.
174      *
175      * @param principals  the identifying attributes of the account, at least one of which should be considered the
176      *                    account's 'primary' identifying attribute, for example, a user id or username.
177      * @param credentials the credentials that verify identity for the account
178      * @param realmName   the name of the realm that accesses this account data
179      * @param roleNames   the names of the roles assigned to this account.
180      * @param permissions the permissions assigned to this account directly (not those assigned to any of the realms).
181      */
182     public SimpleAccount(Collection principals, Object credentials, String realmName, Set<String> roleNames, Set<Permission> permissions) {
183         this.authcInfo = new SimpleAuthenticationInfo(new SimplePrincipalCollection(principals, realmName), credentials);
184         this.authzInfo = new SimpleAuthorizationInfo(roleNames);
185         this.authzInfo.setObjectPermissions(permissions);
186     }
187 
188     /**
189      * Constructs a SimpleAccount instance from the given principals and credentials, with the
190      * the assigned roles and permissions.
191      *
192      * @param principals  the identifying attributes of the account, at least one of which should be considered the
193      *                    account's 'primary' identifying attribute, for example, a user id or username.
194      * @param credentials the credentials that verify identity for the account
195      * @param roleNames   the names of the roles assigned to this account.
196      * @param permissions the permissions assigned to this account directly (not those assigned to any of the realms).
197      */
198     public SimpleAccount(PrincipalCollection principals, Object credentials, Set<String> roleNames, Set<Permission> permissions) {
199         this.authcInfo = new SimpleAuthenticationInfo(principals, credentials);
200         this.authzInfo = new SimpleAuthorizationInfo(roleNames);
201         this.authzInfo.setObjectPermissions(permissions);
202     }
203 
204     /*--------------------------------------------
205     |  A C C E S S O R S / M O D I F I E R S    |
206     ============================================*/
207 
208     /**
209      * Returns the principals, aka the identifying attributes (username, user id, first name, last name, etc) of this
210      * Account.
211      *
212      * @return all the principals, aka the identifying attributes, of this Account.
213      */
214     public PrincipalCollection getPrincipals() {
215         return authcInfo.getPrincipals();
216     }
217 
218     /**
219      * Sets the principals, aka the identifying attributes (username, user id, first name, last name, etc) of this
220      * Account.
221      *
222      * @param principals all the principals, aka the identifying attributes, of this Account.
223      * @see Account#getPrincipals()
224      */
225     public void setPrincipals(PrincipalCollection principals) {
226         this.authcInfo.setPrincipals(principals);
227     }
228 
229 
230     /**
231      * Simply returns <code>this.authcInfo.getCredentials</code>.  The <code>authcInfo</code> attribute is constructed
232      * via the constructors to wrap the input arguments.
233      *
234      * @return this Account's credentials.
235      */
236     public Object getCredentials() {
237         return authcInfo.getCredentials();
238     }
239 
240     /**
241      * Sets this Account's credentials that verify one or more of the Account's
242      * {@link #getPrincipals() principals}, such as a password or private key.
243      *
244      * @param credentials the credentials associated with this Account that verify one or more of the Account principals.
245      * @see org.apache.shiro.authc.Account#getCredentials()
246      */
247     public void setCredentials(Object credentials) {
248         this.authcInfo.setCredentials(credentials);
249     }
250 
251     /**
252      * Returns the salt used to hash this Account's credentials (eg for password hashing), or {@code null} if no salt
253      * was used or credentials were not hashed at all.
254      *
255      * @return the salt used to hash this Account's credentials (eg for password hashing), or {@code null} if no salt
256      *         was used or credentials were not hashed at all.
257      * @since 1.1
258      */
259     public ByteSource getCredentialsSalt() {
260         return this.authcInfo.getCredentialsSalt();
261     }
262 
263     /**
264      * Sets the salt to use to hash this Account's credentials (eg for password hashing), or {@code null} if no salt
265      * is used or credentials are not hashed at all.
266      *
267      * @param salt the salt to use to hash this Account's credentials (eg for password hashing), or {@code null} if no
268      *             salt is used or credentials are not hashed at all.
269      * @since 1.1
270      */
271     public void setCredentialsSalt(ByteSource salt) {
272         this.authcInfo.setCredentialsSalt(salt);
273     }
274 
275     /**
276      * Returns <code>this.authzInfo.getRoles();</code>
277      *
278      * @return the Account's assigned roles.
279      */
280     public Collection<String> getRoles() {
281         return authzInfo.getRoles();
282     }
283 
284     /**
285      * Sets the Account's assigned roles.  Simply calls <code>this.authzInfo.setRoles(roles)</code>.
286      *
287      * @param roles the Account's assigned roles.
288      * @see Account#getRoles()
289      */
290     public void setRoles(Set<String> roles) {
291         this.authzInfo.setRoles(roles);
292     }
293 
294     /**
295      * Adds a role to this Account's set of assigned roles.  Simply delegates to
296      * <code>this.authzInfo.addRole(role)</code>.
297      *
298      * @param role a role to assign to this Account.
299      */
300     public void addRole(String role) {
301         this.authzInfo.addRole(role);
302     }
303 
304     /**
305      * Adds one or more roles to this Account's set of assigned roles. Simply delegates to
306      * <code>this.authzInfo.addRoles(roles)</code>.
307      *
308      * @param roles one or more roles to assign to this Account.
309      */
310     public void addRole(Collection<String> roles) {
311         this.authzInfo.addRoles(roles);
312     }
313 
314     /**
315      * Returns all String-based permissions assigned to this Account.  Simply delegates to
316      * <code>this.authzInfo.getStringPermissions()</code>.
317      *
318      * @return all String-based permissions assigned to this Account.
319      */
320     public Collection<String> getStringPermissions() {
321         return authzInfo.getStringPermissions();
322     }
323 
324     /**
325      * Sets the String-based permissions assigned to this Account.  Simply delegates to
326      * <code>this.authzInfo.setStringPermissions(permissions)</code>.
327      *
328      * @param permissions all String-based permissions assigned to this Account.
329      * @see org.apache.shiro.authc.Account#getStringPermissions()
330      */
331     public void setStringPermissions(Set<String> permissions) {
332         this.authzInfo.setStringPermissions(permissions);
333     }
334 
335     /**
336      * Assigns a String-based permission directly to this Account (not to any of its realms).
337      *
338      * @param permission the String-based permission to assign.
339      */
340     public void addStringPermission(String permission) {
341         this.authzInfo.addStringPermission(permission);
342     }
343 
344     /**
345      * Assigns one or more string-based permissions directly to this Account (not to any of its realms).
346      *
347      * @param permissions one or more String-based permissions to assign.
348      */
349     public void addStringPermissions(Collection<String> permissions) {
350         this.authzInfo.addStringPermissions(permissions);
351     }
352 
353     /**
354      * Returns all object-based permissions assigned directly to this Account (not any of its realms).
355      *
356      * @return all object-based permissions assigned directly to this Account (not any of its realms).
357      */
358     public Collection<Permission> getObjectPermissions() {
359         return authzInfo.getObjectPermissions();
360     }
361 
362     /**
363      * Sets all object-based permissions assigned directly to this Account (not any of its realms).
364      *
365      * @param permissions the object-based permissions to assign directly to this Account.
366      */
367     public void setObjectPermissions(Set<Permission> permissions) {
368         this.authzInfo.setObjectPermissions(permissions);
369     }
370 
371     /**
372      * Assigns an object-based permission directly to this Account (not any of its realms).
373      *
374      * @param permission the object-based permission to assign directly to this Account (not any of its realms).
375      */
376     public void addObjectPermission(Permission permission) {
377         this.authzInfo.addObjectPermission(permission);
378     }
379 
380     /**
381      * Assigns one or more object-based permissions directly to this Account (not any of its realms).
382      *
383      * @param permissions one or more object-based permissions to assign directly to this Account (not any of its realms).
384      */
385     public void addObjectPermissions(Collection<Permission> permissions) {
386         this.authzInfo.addObjectPermissions(permissions);
387     }
388 
389     /**
390      * Returns <code>true</code> if this Account is locked and thus cannot be used to login, <code>false</code> otherwise.
391      *
392      * @return <code>true</code> if this Account is locked and thus cannot be used to login, <code>false</code> otherwise.
393      */
394     public boolean isLocked() {
395         return locked;
396     }
397 
398     /**
399      * Sets whether or not the account is locked and can be used to login.
400      *
401      * @param locked <code>true</code> if this Account is locked and thus cannot be used to login, <code>false</code> otherwise.
402      */
403     public void setLocked(boolean locked) {
404         this.locked = locked;
405     }
406 
407     /**
408      * Returns whether or not the Account's credentials are expired.  This usually indicates that the Subject or an application
409      * administrator would need to change the credentials before the account could be used.
410      *
411      * @return whether or not the Account's credentials are expired.
412      */
413     public boolean isCredentialsExpired() {
414         return credentialsExpired;
415     }
416 
417     /**
418      * Sets whether or not the Account's credentials are expired.  A <code>true</code> value indicates that the Subject
419      * or application administrator would need to change their credentials before the account could be used.
420      *
421      * @param credentialsExpired <code>true</code> if this Account's credentials are expired and need to be changed,
422      *                           <code>false</code> otherwise.
423      */
424     public void setCredentialsExpired(boolean credentialsExpired) {
425         this.credentialsExpired = credentialsExpired;
426     }
427 
428 
429     /**
430      * Merges the specified <code>AuthenticationInfo</code> into this <code>Account</code>.
431      * <p/>
432      * If the specified argument is also an instance of {@link SimpleAccount SimpleAccount}, the
433      * {@link #isLocked()} and {@link #isCredentialsExpired()} attributes are merged (set on this instance) as well
434      * (only if their values are <code>true</code>).
435      *
436      * @param info the <code>AuthenticationInfo</code> to merge into this account.
437      */
438     public void merge(AuthenticationInfo info) {
439         authcInfo.merge(info);
440 
441         // Merge SimpleAccount specific info
442         if (info instanceof SimpleAccount) {
443             SimpleAccount otherAccount = (SimpleAccount) info;
444             if (otherAccount.isLocked()) {
445                 setLocked(true);
446             }
447 
448             if (otherAccount.isCredentialsExpired()) {
449                 setCredentialsExpired(true);
450             }
451         }
452     }
453 
454     /**
455      * If the {@link #getPrincipals() principals} are not null, returns <code>principals.hashCode()</code>, otherwise
456      * returns 0 (zero).
457      *
458      * @return <code>principals.hashCode()</code> if they are not null, 0 (zero) otherwise.
459      */
460     public int hashCode() {
461         return (getPrincipals() != null ? getPrincipals().hashCode() : 0);
462     }
463 
464     /**
465      * Returns <code>true</code> if the specified object is also a {@link SimpleAccount SimpleAccount} and its
466      * {@link #getPrincipals() principals} are equal to this object's <code>principals</code>, <code>false</code> otherwise.
467      *
468      * @param o the object to test for equality.
469      * @return <code>true</code> if the specified object is also a {@link SimpleAccount SimpleAccount} and its
470      *         {@link #getPrincipals() principals} are equal to this object's <code>principals</code>, <code>false</code> otherwise.
471      */
472     public boolean equals(Object o) {
473         if (o == this) {
474             return true;
475         }
476         if (o instanceof SimpleAccount) {
477             SimpleAccount sa = (SimpleAccount) o;
478             //principal should be unique across the application, so only check this for equality:
479             return (getPrincipals() != null ? getPrincipals().equals(sa.getPrincipals()) : sa.getPrincipals() == null);
480         }
481         return false;
482     }
483 
484     /**
485      * Returns {@link #getPrincipals() principals}.toString() if they are not null, otherwise prints out the string
486      * &quot;empty&quot;
487      *
488      * @return the String representation of this Account object.
489      */
490     public String toString() {
491         return getPrincipals() != null ? getPrincipals().toString() : "empty";
492     }
493 
494 }