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    
026    import java.io.Serializable;
027    import java.util.Collection;
028    import java.util.Set;
029    
030    
031    /**
032     * Simple implementation of the {@link org.apache.shiro.authc.Account} interface that
033     * contains principal and credential and authorization information (roles and permissions) as instance variables and
034     * exposes them via getters and setters using standard JavaBean notation.
035     *
036     * @author Jeremy Haile
037     * @author Les Hazlewood
038     * @since 0.1
039     */
040    public class SimpleAccount implements Account, MergableAuthenticationInfo, Serializable {
041    
042        /*--------------------------------------------
043        |    I N S T A N C E   V A R I A B L E S    |
044        ============================================*/
045        /**
046         * The authentication information (principals and credentials) for this account.
047         */
048        private SimpleAuthenticationInfo authcInfo;
049    
050        /**
051         * The authorization information for this account.
052         */
053        private SimpleAuthorizationInfo authzInfo;
054    
055        /**
056         * Indicates this account is locked.  This isn't honored by all <tt>Realms</tt> but is honored by
057         * {@link org.apache.shiro.realm.SimpleAccountRealm}.
058         */
059        private boolean locked;
060    
061        /**
062         * Indicates credentials on this account are expired.  This isn't honored by all <tt>Realms</tt> but is honored by
063         * {@link org.apache.shiro.realm.SimpleAccountRealm}.
064         */
065        private boolean credentialsExpired;
066    
067        /*--------------------------------------------
068        |         C O N S T R U C T O R S           |
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 and credentials.
089         *
090         * @param principals  the identifying attributes of the account, at least one of which should be considered the
091         *                    account's 'primary' identifying attribute, for example, a user id or username.
092         * @param credentials the credentials that verify identity for the account
093         * @param realmName   the name of the realm that accesses this account data
094         */
095        public SimpleAccount(Collection principals, Object credentials, String realmName) {
096            this(new SimplePrincipalCollection(principals, realmName), credentials);
097        }
098    
099        /**
100         * Constructs a SimpleAccount instance for the specified principals and credentials.
101         *
102         * @param principals  the identifying attributes of the account, at least one of which should be considered the
103         *                    account's 'primary' identifying attribute, for example, a user id or username.
104         * @param credentials the credentials that verify identity for the account
105         */
106        public SimpleAccount(PrincipalCollection principals, Object credentials) {
107            this.authcInfo = new SimpleAuthenticationInfo(principals, credentials);
108            this.authzInfo = new SimpleAuthorizationInfo();
109        }
110    
111        /**
112         * Constructs a SimpleAccount instance for the specified principals and credentials, with the assigned roles.
113         *
114         * @param principals  the identifying attributes of the account, at least one of which should be considered the
115         *                    account's 'primary' identifying attribute, for example, a user id or username.
116         * @param credentials the credentials that verify identity for the account
117         * @param roles       the names of the roles assigned to this account.
118         */
119        public SimpleAccount(PrincipalCollection principals, Object credentials, Set<String> roles) {
120            this.authcInfo = new SimpleAuthenticationInfo(principals, credentials);
121            this.authzInfo = new SimpleAuthorizationInfo(roles);
122        }
123    
124        /**
125         * Constructs a SimpleAccount instance for the specified realm with the given principal and credentials, with the
126         * the assigned roles and permissions.
127         *
128         * @param principal   the 'primary' identifying attributes of the account, for example, a user id or username.
129         * @param credentials the credentials that verify identity for the account
130         * @param realmName   the name of the realm that accesses this account data
131         * @param roleNames   the names of the roles assigned to this account.
132         * @param permissions the permissions assigned to this account directly (not those assigned to any of the realms).
133         */
134        public SimpleAccount(Object principal, Object credentials, String realmName, Set<String> roleNames, Set<Permission> permissions) {
135            this.authcInfo = new SimpleAuthenticationInfo(new SimplePrincipalCollection(principal, realmName), credentials);
136            this.authzInfo = new SimpleAuthorizationInfo(roleNames);
137            this.authzInfo.setObjectPermissions(permissions);
138        }
139    
140        /**
141         * Constructs a SimpleAccount instance for the specified realm with the given principals and credentials, with the
142         * the assigned roles and permissions.
143         *
144         * @param principals  the identifying attributes of the account, at least one of which should be considered the
145         *                    account's 'primary' identifying attribute, for example, a user id or username.
146         * @param credentials the credentials that verify identity for the account
147         * @param realmName   the name of the realm that accesses this account data
148         * @param roleNames   the names of the roles assigned to this account.
149         * @param permissions the permissions assigned to this account directly (not those assigned to any of the realms).
150         */
151        public SimpleAccount(Collection principals, Object credentials, String realmName, Set<String> roleNames, Set<Permission> permissions) {
152            this.authcInfo = new SimpleAuthenticationInfo(new SimplePrincipalCollection(principals, realmName), credentials);
153            this.authzInfo = new SimpleAuthorizationInfo(roleNames);
154            this.authzInfo.setObjectPermissions(permissions);
155        }
156    
157        /**
158         * Constructs a SimpleAccount instance from the given principals and credentials, with the
159         * the assigned roles and permissions.
160         *
161         * @param principals  the identifying attributes of the account, at least one of which should be considered the
162         *                    account's 'primary' identifying attribute, for example, a user id or username.
163         * @param credentials the credentials that verify identity for the account
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(PrincipalCollection principals, Object credentials, Set<String> roleNames, Set<Permission> permissions) {
168            this.authcInfo = new SimpleAuthenticationInfo(principals, credentials);
169            this.authzInfo = new SimpleAuthorizationInfo(roleNames);
170            this.authzInfo.setObjectPermissions(permissions);
171        }
172    
173        /*--------------------------------------------
174        |  A C C E S S O R S / M O D I F I E R S    |
175        ============================================*/
176    
177        /**
178         * Returns the principals, aka the identifying attributes (username, user id, first name, last name, etc) of this
179         * Account.
180         *
181         * @return all the principals, aka the identifying attributes, of this Account.
182         */
183        public PrincipalCollection getPrincipals() {
184            return authcInfo.getPrincipals();
185        }
186    
187        /**
188         * Sets the principals, aka the identifying attributes (username, user id, first name, last name, etc) of this
189         * Account.
190         *
191         * @param principals all the principals, aka the identifying attributes, of this Account.
192         * @see Account#getPrincipals()
193         */
194        public void setPrincipals(PrincipalCollection principals) {
195            this.authcInfo.setPrincipals(principals);
196        }
197    
198    
199        /**
200         * Simply returns <code>this.authcInfo.getCredentials</code>.  The <code>authcInfo</code> attribute is constructed
201         * via the constructors to wrap the input arguments.
202         *
203         * @return this Account's credentials.
204         */
205        public Object getCredentials() {
206            return authcInfo.getCredentials();
207        }
208    
209        /**
210         * Sets this Account's credentials that verify one or more of the Account's
211         * {@link #getPrincipals() principals}, such as a password or private key.
212         *
213         * @param credentials the credentials associated with this Account that verify one or more of the Account principals.
214         * @see org.apache.shiro.authc.Account#getCredentials()
215         */
216        public void setCredentials(Object credentials) {
217            this.authcInfo.setCredentials(credentials);
218        }
219    
220        /**
221         * Returns <code>this.authzInfo.getRoles();</code>
222         *
223         * @return the Account's assigned roles.
224         */
225        public Collection<String> getRoles() {
226            return authzInfo.getRoles();
227        }
228    
229        /**
230         * Sets the Account's assigned roles.  Simply calls <code>this.authzInfo.setRoles(roles)</code>.
231         *
232         * @param roles the Account's assigned roles.
233         * @see Account#getRoles()
234         */
235        public void setRoles(Set<String> roles) {
236            this.authzInfo.setRoles(roles);
237        }
238    
239        /**
240         * Adds a role to this Account's set of assigned roles.  Simply delegates to
241         * <code>this.authzInfo.addRole(role)</code>.
242         *
243         * @param role a role to assign to this Account.
244         */
245        public void addRole(String role) {
246            this.authzInfo.addRole(role);
247        }
248    
249        /**
250         * Adds one or more roles to this Account's set of assigned roles. Simply delegates to
251         * <code>this.authzInfo.addRoles(roles)</code>.
252         *
253         * @param roles one or more roles to assign to this Account.
254         */
255        public void addRole(Collection<String> roles) {
256            this.authzInfo.addRoles(roles);
257        }
258    
259        /**
260         * Returns all String-based permissions assigned to this Account.  Simply delegates to
261         * <code>this.authzInfo.getStringPermissions()</code>.
262         *
263         * @return all String-based permissions assigned to this Account.
264         */
265        public Collection<String> getStringPermissions() {
266            return authzInfo.getStringPermissions();
267        }
268    
269        /**
270         * Sets the String-based permissions assigned to this Account.  Simply delegates to
271         * <code>this.authzInfo.setStringPermissions(permissions)</code>.
272         *
273         * @param permissions all String-based permissions assigned to this Account.
274         * @see org.apache.shiro.authc.Account#getStringPermissions()
275         */
276        public void setStringPermissions(Set<String> permissions) {
277            this.authzInfo.setStringPermissions(permissions);
278        }
279    
280        /**
281         * Assigns a String-based permission directly to this Account (not to any of its realms).
282         *
283         * @param permission the String-based permission to assign.
284         */
285        public void addStringPermission(String permission) {
286            this.authzInfo.addStringPermission(permission);
287        }
288    
289        /**
290         * Assigns one or more string-based permissions directly to this Account (not to any of its realms).
291         *
292         * @param permissions one or more String-based permissions to assign.
293         */
294        public void addStringPermissions(Collection<String> permissions) {
295            this.authzInfo.addStringPermissions(permissions);
296        }
297    
298        /**
299         * Returns all object-based permissions assigned directly to this Account (not any of its realms).
300         *
301         * @return all object-based permissions assigned directly to this Account (not any of its realms).
302         */
303        public Collection<Permission> getObjectPermissions() {
304            return authzInfo.getObjectPermissions();
305        }
306    
307        /**
308         * Sets all object-based permissions assigned directly to this Account (not any of its realms).
309         *
310         * @param permissions the object-based permissions to assign directly to this Account.
311         */
312        public void setObjectPermissions(Set<Permission> permissions) {
313            this.authzInfo.setObjectPermissions(permissions);
314        }
315    
316        /**
317         * Assigns an object-based permission directly to this Account (not any of its realms).
318         *
319         * @param permission the object-based permission to assign directly to this Account (not any of its realms).
320         */
321        public void addObjectPermission(Permission permission) {
322            this.authzInfo.addObjectPermission(permission);
323        }
324    
325        /**
326         * Assigns one or more object-based permissions directly to this Account (not any of its realms).
327         *
328         * @param permissions one or more object-based permissions to assign directly to this Account (not any of its realms).
329         */
330        public void addObjectPermissions(Collection<Permission> permissions) {
331            this.authzInfo.addObjectPermissions(permissions);
332        }
333    
334        /**
335         * Returns <code>true</code> if this Account is locked and thus cannot be used to login, <code>false</code> otherwise.
336         *
337         * @return <code>true</code> if this Account is locked and thus cannot be used to login, <code>false</code> otherwise.
338         */
339        public boolean isLocked() {
340            return locked;
341        }
342    
343        /**
344         * Sets whether or not the account is locked and can be used to login.
345         *
346         * @param locked <code>true</code> if this Account is locked and thus cannot be used to login, <code>false</code> otherwise.
347         */
348        public void setLocked(boolean locked) {
349            this.locked = locked;
350        }
351    
352        /**
353         * Returns whether or not the Account's credentials are expired.  This usually indicates that the Subject or an application
354         * administrator would need to change the credentials before the account could be used.
355         *
356         * @return whether or not the Account's credentials are expired.
357         */
358        public boolean isCredentialsExpired() {
359            return credentialsExpired;
360        }
361    
362        /**
363         * Sets whether or not the Account's credentials are expired.  A <code>true</code> value indicates that the Subject
364         * or application administrator would need to change their credentials before the account could be used.
365         *
366         * @param credentialsExpired <code>true</code> if this Account's credentials are expired and need to be changed,
367         *                           <code>false</code> otherwise.
368         */
369        public void setCredentialsExpired(boolean credentialsExpired) {
370            this.credentialsExpired = credentialsExpired;
371        }
372    
373    
374        /**
375         * Merges the specified <code>AuthenticationInfo</code> into this <code>Account</code>.
376         * <p/>
377         * If the specified argument is also an instance of {@link SimpleAccount SimpleAccount}, the
378         * {@link #isLocked()} and {@link #isCredentialsExpired()} attributes are merged (set on this instance) as well
379         * (only if their values are <code>true</code>).
380         *
381         * @param info the <code>AuthenticationInfo</code> to merge into this account.
382         */
383        public void merge(AuthenticationInfo info) {
384            authcInfo.merge(info);
385    
386            // Merge SimpleAccount specific info
387            if (info instanceof SimpleAccount) {
388                SimpleAccount otherAccount = (SimpleAccount) info;
389                if (otherAccount.isLocked()) {
390                    setLocked(true);
391                }
392    
393                if (otherAccount.isCredentialsExpired()) {
394                    setCredentialsExpired(true);
395                }
396            }
397        }
398    
399        /**
400         * If the {@link #getPrincipals() principals} are not null, returns <code>principals.hashCode()</code>, otherwise
401         * returns 0 (zero).
402         *
403         * @return <code>principals.hashCode()</code> if they are not null, 0 (zero) otherwise.
404         */
405        public int hashCode() {
406            return (getPrincipals() != null ? getPrincipals().hashCode() : 0);
407        }
408    
409        /**
410         * Returns <code>true</code> if the specified object is also a {@link SimpleAccount SimpleAccount} and its
411         * {@link #getPrincipals() principals} are equal to this object's <code>principals</code>, <code>false</code> otherwise.
412         *
413         * @param o the object to test for equality.
414         * @return <code>true</code> if the specified object is also a {@link SimpleAccount SimpleAccount} and its
415         *         {@link #getPrincipals() principals} are equal to this object's <code>principals</code>, <code>false</code> otherwise.
416         */
417        public boolean equals(Object o) {
418            if (o == this) {
419                return true;
420            }
421            if (o instanceof SimpleAccount) {
422                SimpleAccount sa = (SimpleAccount) o;
423                //principal should be unique across the application, so only check this for equality:
424                return (getPrincipals() != null ? getPrincipals().equals(sa.getPrincipals()) : sa.getPrincipals() == null);
425            }
426            return false;
427        }
428    
429        /**
430         * Returns {@link #getPrincipals() principals}.toString() if they are not null, otherwise prints out the string
431         * &quot;empty&quot;
432         *
433         * @return the String representation of this Account object.
434         */
435        public String toString() {
436            return getPrincipals() != null ? getPrincipals().toString() : "empty";
437        }
438    
439    }