001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    package org.apache.shiro.authc;
020    
021    import org.apache.shiro.authz.Permission;
022    import org.apache.shiro.authz.SimpleAuthorizationInfo;
023    import org.apache.shiro.subject.PrincipalCollection;
024    import org.apache.shiro.subject.SimplePrincipalCollection;
025    import org.apache.shiro.util.ByteSource;
026    
027    import java.io.Serializable;
028    import java.util.Collection;
029    import java.util.Set;
030    
031    
032    /**
033     * Simple implementation of the {@link org.apache.shiro.authc.Account} interface that
034     * contains principal and credential and authorization information (roles and permissions) as instance variables and
035     * exposes them via getters and setters using standard JavaBean notation.
036     *
037     * @since 0.1
038     */
039    public class SimpleAccount implements Account, MergableAuthenticationInfo, SaltedAuthenticationInfo, Serializable {
040    
041        /*--------------------------------------------
042        |    I N S T A N C E   V A R I A B L E S    |
043        ============================================*/
044        /**
045         * The authentication information (principals and credentials) for this account.
046         */
047        private SimpleAuthenticationInfo authcInfo;
048    
049        /**
050         * The authorization information for this account.
051         */
052        private SimpleAuthorizationInfo authzInfo;
053    
054        /**
055         * Indicates this account is locked.  This isn't honored by all <tt>Realms</tt> but is honored by
056         * {@link org.apache.shiro.realm.SimpleAccountRealm}.
057         */
058        private boolean locked;
059    
060        /**
061         * Indicates credentials on this account are expired.  This isn't honored by all <tt>Realms</tt> but is honored by
062         * {@link org.apache.shiro.realm.SimpleAccountRealm}.
063         */
064        private boolean credentialsExpired;
065    
066        /*--------------------------------------------
067        |         C O N S T R U C T O R S           |
068        ============================================*/
069    
070        /**
071         * Default no-argument constructor.
072         */
073        public SimpleAccount() {
074        }
075    
076        /**
077         * Constructs a SimpleAccount instance for the specified realm with the given principals and credentials.
078         *
079         * @param principal   the 'primary' identifying attribute of the account, for example, a user id or username.
080         * @param credentials the credentials that verify identity for the account
081         * @param realmName   the name of the realm that accesses this account data
082         */
083        public SimpleAccount(Object principal, Object credentials, String realmName) {
084            this(principal instanceof PrincipalCollection ? (PrincipalCollection) principal : new SimplePrincipalCollection(principal, realmName), credentials);
085        }
086    
087        /**
088         * Constructs a SimpleAccount instance for the specified realm with the given principals, hashedCredentials and
089         * credentials salt used when hashing the credentials.
090         *
091         * @param principal         the 'primary' identifying attribute of the account, for example, a user id or username.
092         * @param hashedCredentials the credentials that verify identity for the account
093         * @param credentialsSalt   the salt used when hashing the credentials
094         * @param realmName         the name of the realm that accesses this account data
095         * @see org.apache.shiro.authc.credential.HashedCredentialsMatcher HashedCredentialsMatcher
096         * @since 1.1
097         */
098        public SimpleAccount(Object principal, Object hashedCredentials, ByteSource credentialsSalt, String realmName) {
099            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    }