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