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