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 * "empty"
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 }