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.subject;
20
21 import org.apache.shiro.SecurityUtils;
22 import org.apache.shiro.authc.AuthenticationException;
23 import org.apache.shiro.authc.AuthenticationToken;
24 import org.apache.shiro.authz.AuthorizationException;
25 import org.apache.shiro.authz.Permission;
26 import org.apache.shiro.mgt.SecurityManager;
27 import org.apache.shiro.mgt.SubjectFactory;
28 import org.apache.shiro.session.Session;
29 import org.apache.shiro.subject.support.DefaultSubjectContext;
30 import org.apache.shiro.lang.util.StringUtils;
31
32 import java.io.Serializable;
33 import java.util.Collection;
34 import java.util.List;
35 import java.util.concurrent.Callable;
36
37 /**
38 * A {@code Subject} represents state and security operations for a <em>single</em> application user.
39 * These operations include authentication (login/logout), authorization (access control), and
40 * session access. It is Shiro's primary mechanism for single-user security functionality.
41 * <h3>Acquiring a Subject</h3>
42 * To acquire the currently-executing {@code Subject}, application developers will almost always use
43 * {@code SecurityUtils}:
44 * <pre>
45 * {@link SecurityUtils SecurityUtils}.{@link org.apache.shiro.SecurityUtils#getSubject() getSubject()}</pre>
46 * Almost all security operations should be performed with the {@code Subject} returned from this method.
47 * <h3>Permission methods</h3>
48 * Note that there are many *Permission methods in this interface overloaded to accept String arguments instead of
49 * {@link Permission Permission} instances. They are a convenience allowing the caller to use a String representation of
50 * a {@link Permission Permission} if desired. The underlying Authorization subsystem implementations will usually
51 * simply convert these String values to {@link Permission Permission} instances and then just call the corresponding
52 * type-safe method. (Shiro's default implementations do String-to-Permission conversion for these methods using
53 * {@link org.apache.shiro.authz.permission.PermissionResolver PermissionResolver}s.)
54 * <p/>
55 * These overloaded *Permission methods forgo type-safety for the benefit of convenience and simplicity,
56 * so you should choose which ones to use based on your preferences and needs.
57 *
58 * @since 0.1
59 */
60 @SuppressWarnings("checkstyle:MethodCount")
61 public interface Subject {
62
63 /**
64 * Returns this Subject's application-wide uniquely identifying principal, or {@code null} if this
65 * Subject is anonymous because it doesn't yet have any associated account data (for example,
66 * if they haven't logged in).
67 * <p/>
68 * The term <em>principal</em> is just a fancy security term for any identifying attribute(s) of an application
69 * user, such as a username, or user id, or public key, or anything else you might use in your application to
70 * identify a user.
71 * <h4>Uniqueness</h4>
72 * Although given names and family names (first/last) are technically considered principals as well,
73 * Shiro expects the object returned from this method to be an identifying attribute unique across
74 * your entire application.
75 * <p/>
76 * This implies that things like given names and family names are usually poor
77 * candidates as return values since they are rarely guaranteed to be unique; Things often used for this value:
78 * <ul>
79 * <li>A {@code long} RDBMS surrogate primary key</li>
80 * <li>An application-unique username</li>
81 * <li>A {@link java.util.UUID UUID}</li>
82 * <li>An LDAP Unique ID</li>
83 * </ul>
84 * or any other similar suitable unique mechanism valuable to your application.
85 * <p/>
86 * Most implementations will simply return
87 * <code>{@link #getPrincipals()}.
88 * {@link org.apache.shiro.subject.PrincipalCollection#getPrimaryPrincipal() getPrimaryPrincipal()}</code>
89 *
90 * @return this Subject's application-specific unique identity.
91 * @see org.apache.shiro.subject.PrincipalCollection#getPrimaryPrincipal()
92 */
93 Object getPrincipal();
94
95 /**
96 * Returns this Subject's principals (identifying attributes) in the form of a {@code PrincipalCollection} or
97 * {@code null} if this Subject is anonymous because it doesn't yet have any associated account data (for example,
98 * if they haven't logged in).
99 * <p/>
100 * The word "principals" is nothing more than a fancy security term for identifying attributes associated
101 * with a Subject, aka, application user. For example, user id, a surname (family/last name), given (first) name,
102 * social security number, nickname, username, etc., are all examples of a principal.
103 *
104 * @return all of this Subject's principals (identifying attributes).
105 * @see #getPrincipal()
106 * @see org.apache.shiro.subject.PrincipalCollection#getPrimaryPrincipal()
107 */
108 PrincipalCollection getPrincipals();
109
110 /**
111 * Returns {@code true} if this Subject is permitted to perform an action or access a resource summarized by the
112 * specified permission string.
113 * <p/>
114 * This is an overloaded method for the corresponding type-safe {@link Permission Permission} variant.
115 * Please see the class-level JavaDoc for more information on these String-based permission methods.
116 *
117 * @param permission the String representation of a Permission that is being checked.
118 * @return true if this Subject is permitted, false otherwise.
119 * @see #isPermitted(Permission permission)
120 * @since 0.9
121 */
122 boolean isPermitted(String permission);
123
124 /**
125 * Returns {@code true} if this Subject is permitted to perform an action or access a resource summarized by the
126 * specified permission.
127 * <p/>
128 * More specifically, this method determines if any {@code Permission}s associated
129 * with the subject {@link Permission#implies(Permission) imply} the specified permission.
130 *
131 * @param permission the permission that is being checked.
132 * @return true if this Subject is permitted, false otherwise.
133 */
134 boolean isPermitted(Permission permission);
135
136 /**
137 * Checks if this Subject implies the given permission strings and returns a boolean array indicating which
138 * permissions are implied.
139 * <p/>
140 * This is an overloaded method for the corresponding type-safe {@link Permission Permission} variant.
141 * Please see the class-level JavaDoc for more information on these String-based permission methods.
142 *
143 * @param permissions the String representations of the Permissions that are being checked.
144 * @return a boolean array where indices correspond to the index of the
145 * permissions in the given list. A true value at an index indicates this Subject is permitted for
146 * for the associated {@code Permission} string in the list. A false value at an index
147 * indicates otherwise.
148 * @since 0.9
149 */
150 boolean[] isPermitted(String... permissions);
151
152 /**
153 * Checks if this Subject implies the given Permissions and returns a boolean array indicating which permissions
154 * are implied.
155 * <p/>
156 * More specifically, this method should determine if each {@code Permission} in
157 * the array is {@link Permission#implies(Permission) implied} by permissions
158 * already associated with the subject.
159 * <p/>
160 * This is primarily a performance-enhancing method to help reduce the number of
161 * {@link #isPermitted} invocations over the wire in client/server systems.
162 *
163 * @param permissions the permissions that are being checked.
164 * @return a boolean array where indices correspond to the index of the
165 * permissions in the given list. A true value at an index indicates this Subject is permitted for
166 * for the associated {@code Permission} object in the list. A false value at an index
167 * indicates otherwise.
168 */
169 boolean[] isPermitted(List<Permission> permissions);
170
171 /**
172 * Returns {@code true} if this Subject implies all of the specified permission strings, {@code false} otherwise.
173 * <p/>
174 * This is an overloaded method for the corresponding type-safe {@link org.apache.shiro.authz.Permission Permission}
175 * variant. Please see the class-level JavaDoc for more information on these String-based permission methods.
176 *
177 * @param permissions the String representations of the Permissions that are being checked.
178 * @return true if this Subject has all of the specified permissions, false otherwise.
179 * @see #isPermittedAll(Collection)
180 * @since 0.9
181 */
182 boolean isPermittedAll(String... permissions);
183
184 /**
185 * Returns {@code true} if this Subject implies all of the specified permissions, {@code false} otherwise.
186 * <p/>
187 * More specifically, this method determines if all of the given {@code Permission}s are
188 * {@link Permission#implies(Permission) implied by} permissions already associated with this Subject.
189 *
190 * @param permissions the permissions to check.
191 * @return true if this Subject has all of the specified permissions, false otherwise.
192 */
193 boolean isPermittedAll(Collection<Permission> permissions);
194
195 /**
196 * Ensures this Subject implies the specified permission String.
197 * <p/>
198 * If this subject's existing associated permissions do not {@link Permission#implies(Permission)} imply}
199 * the given permission, an {@link org.apache.shiro.authz.AuthorizationException} will be thrown.
200 * <p/>
201 * This is an overloaded method for the corresponding type-safe {@link Permission Permission} variant.
202 * Please see the class-level JavaDoc for more information on these String-based permission methods.
203 *
204 * @param permission the String representation of the Permission to check.
205 * @throws org.apache.shiro.authz.AuthorizationException if the user does not have the permission.
206 * @since 0.9
207 */
208 void checkPermission(String permission) throws AuthorizationException;
209
210 /**
211 * Ensures this Subject {@link Permission#implies(Permission) implies} the specified {@code Permission}.
212 * <p/>
213 * If this subject's existing associated permissions do not {@link Permission#implies(Permission) imply}
214 * the given permission, an {@link org.apache.shiro.authz.AuthorizationException} will be thrown.
215 *
216 * @param permission the Permission to check.
217 * @throws org.apache.shiro.authz.AuthorizationException if this Subject does not have the permission.
218 */
219 void checkPermission(Permission permission) throws AuthorizationException;
220
221 /**
222 * Ensures this Subject
223 * {@link org.apache.shiro.authz.Permission#implies(org.apache.shiro.authz.Permission) implies} all of the
224 * specified permission strings.
225 * <p/>
226 * If this subject's existing associated permissions do not
227 * {@link org.apache.shiro.authz.Permission#implies(org.apache.shiro.authz.Permission) imply} all of the given permissions,
228 * an {@link org.apache.shiro.authz.AuthorizationException} will be thrown.
229 * <p/>
230 * This is an overloaded method for the corresponding type-safe {@link Permission Permission} variant.
231 * Please see the class-level JavaDoc for more information on these String-based permission methods.
232 *
233 * @param permissions the string representations of Permissions to check.
234 * @throws AuthorizationException if this Subject does not have all of the given permissions.
235 * @since 0.9
236 */
237 void checkPermissions(String... permissions) throws AuthorizationException;
238
239 /**
240 * Ensures this Subject
241 * {@link org.apache.shiro.authz.Permission#implies(org.apache.shiro.authz.Permission) implies} all of the
242 * specified permission strings.
243 * <p/>
244 * If this subject's existing associated permissions do not
245 * {@link org.apache.shiro.authz.Permission#implies(org.apache.shiro.authz.Permission) imply} all of the given permissions,
246 * an {@link org.apache.shiro.authz.AuthorizationException} will be thrown.
247 *
248 * @param permissions the Permissions to check.
249 * @throws AuthorizationException if this Subject does not have all of the given permissions.
250 */
251 void checkPermissions(Collection<Permission> permissions) throws AuthorizationException;
252
253 /**
254 * Returns {@code true} if this Subject has the specified role, {@code false} otherwise.
255 *
256 * @param roleIdentifier the application-specific role identifier (usually a role id or role name).
257 * @return {@code true} if this Subject has the specified role, {@code false} otherwise.
258 */
259 boolean hasRole(String roleIdentifier);
260
261 /**
262 * Checks if this Subject has the specified roles, returning a boolean array indicating
263 * which roles are associated.
264 * <p/>
265 * This is primarily a performance-enhancing method to help reduce the number of
266 * {@link #hasRole} invocations over the wire in client/server systems.
267 *
268 * @param roleIdentifiers the application-specific role identifiers to check (usually role ids or role names).
269 * @return a boolean array where indices correspond to the index of the
270 * roles in the given identifiers. A true value indicates this Subject has the
271 * role at that index. False indicates this Subject does not have the role at that index.
272 */
273 boolean[] hasRoles(List<String> roleIdentifiers);
274
275 /**
276 * Returns {@code true} if this Subject has all of the specified roles, {@code false} otherwise.
277 *
278 * @param roleIdentifiers the application-specific role identifiers to check (usually role ids or role names).
279 * @return true if this Subject has all the roles, false otherwise.
280 */
281 boolean hasAllRoles(Collection<String> roleIdentifiers);
282
283 /**
284 * Asserts this Subject has the specified role by returning quietly if they do or throwing an
285 * {@link org.apache.shiro.authz.AuthorizationException} if they do not.
286 *
287 * @param roleIdentifier the application-specific role identifier (usually a role id or role name ).
288 * @throws org.apache.shiro.authz.AuthorizationException if this Subject does not have the role.
289 */
290 void checkRole(String roleIdentifier) throws AuthorizationException;
291
292 /**
293 * Asserts this Subject has all of the specified roles by returning quietly if they do or throwing an
294 * {@link org.apache.shiro.authz.AuthorizationException} if they do not.
295 *
296 * @param roleIdentifiers the application-specific role identifiers to check (usually role ids or role names).
297 * @throws org.apache.shiro.authz.AuthorizationException if this Subject does not have all of the specified roles.
298 */
299 void checkRoles(Collection<String> roleIdentifiers) throws AuthorizationException;
300
301 /**
302 * Same as {@link #checkRoles(Collection<String> roleIdentifiers) checkRoles(Collection<String> roleIdentifiers)} but
303 * doesn't require a collection as a an argument.
304 * Asserts this Subject has all of the specified roles by returning quietly if they do or throwing an
305 * {@link org.apache.shiro.authz.AuthorizationException} if they do not.
306 *
307 * @param roleIdentifiers roleIdentifiers the application-specific role identifiers to check (usually role ids or role names).
308 * @throws AuthorizationException org.apache.shiro.authz.AuthorizationException
309 * if this Subject does not have all of the specified roles.
310 * @since 1.1.0
311 */
312 void checkRoles(String... roleIdentifiers) throws AuthorizationException;
313
314 /**
315 * Performs a login attempt for this Subject/user. If unsuccessful,
316 * an {@link AuthenticationException} is thrown, the subclass of which identifies why the attempt failed.
317 * If successful, the account data associated with the submitted principals/credentials will be
318 * associated with this {@code Subject} and the method will return quietly.
319 * <p/>
320 * Upon returning quietly, this {@code Subject} instance can be considered
321 * authenticated and {@link #getPrincipal() getPrincipal()} will be non-null and
322 * {@link #isAuthenticated() isAuthenticated()} will be {@code true}.
323 *
324 * @param token the token encapsulating the subject's principals and credentials to be passed to the
325 * Authentication subsystem for verification.
326 * @throws org.apache.shiro.authc.AuthenticationException if the authentication attempt fails.
327 * @since 0.9
328 */
329 void login(AuthenticationToken token) throws AuthenticationException;
330
331 /**
332 * Returns {@code true} if this Subject/user proved their identity <em>during their current session</em>
333 * by providing valid credentials matching those known to the system, {@code false} otherwise.
334 * <p/>
335 * Note that even if this Subject's identity has been remembered via 'remember me' services, this method will
336 * still return {@code false} unless the user has actually logged in with proper credentials <em>during their
337 * current session</em>. See the {@link #isRemembered() isRemembered()} method JavaDoc for more.
338 *
339 * @return {@code true} if this Subject proved their identity during their current session
340 * by providing valid credentials matching those known to the system, {@code false} otherwise.
341 * @since 0.9
342 */
343 boolean isAuthenticated();
344
345
346 /**
347 * Returns {@code true} if this {@code Subject} has an identity (it is not anonymous) and the identity
348 * (aka {@link #getPrincipals() principals}) is remembered from a successful authentication during a previous
349 * session.
350 * <p/>
351 * Although the underlying implementation determines exactly how this method functions, most implementations have
352 * this method act as the logical equivalent to this code:
353 * <pre>
354 * {@link #getPrincipal() getPrincipal()} != null && !{@link #isAuthenticated() isAuthenticated()}</pre>
355 * <p/>
356 * Note as indicated by the above code example, if a {@code Subject} is remembered, they are
357 * <em>NOT</em> considered authenticated. A check against {@link #isAuthenticated() isAuthenticated()} is a more
358 * strict check than that reflected by this method. For example, a check to see if a subject can access financial
359 * information should almost always depend on {@link #isAuthenticated() isAuthenticated()} to <em>guarantee</em> a
360 * verified identity, and not this method.
361 * <p/>
362 * Once the subject is authenticated, they are no longer considered only remembered because their identity would
363 * have been verified during the current session.
364 * <h4>Remembered vs Authenticated</h4>
365 * Authentication is the process of <em>proving</em> you are who you say you are. When a user is only remembered,
366 * the remembered identity gives the system an idea who that user probably is, but in reality, has no way of
367 * absolutely <em>guaranteeing</em> if the remembered {@code Subject} represents the user currently
368 * using the application.
369 * <p/>
370 * So although many parts of the application can still perform user-specific logic based on the remembered
371 * {@link #getPrincipals() principals}, such as customized views, it should never perform highly-sensitive
372 * operations until the user has legitimately verified their identity by executing a successful authentication
373 * attempt.
374 * <p/>
375 * We see this paradigm all over the web, and we will use <a href="http://www.amazon.com">Amazon.com</a> as an
376 * example:
377 * <p/>
378 * When you visit Amazon.com and perform a login and ask it to 'remember me', it will set a cookie with your
379 * identity. If you don't log out and your session expires, and you come back, say the next day, Amazon still knows
380 * who you <em>probably</em> are: you still see all of your book and movie recommendations and similar user-specific
381 * features since these are based on your (remembered) user id.
382 * <p/>
383 * BUT, if you try to do something sensitive, such as access your account's billing data, Amazon forces you
384 * to do an actual log-in, requiring your username and password.
385 * <p/>
386 * This is because although amazon.com assumed your identity from 'remember me', it recognized that you were not
387 * actually authenticated. The only way to really guarantee you are who you say you are, and therefore allow you
388 * access to sensitive account data, is to force you to perform an actual successful authentication. You can
389 * check this guarantee via the {@link #isAuthenticated() isAuthenticated()} method and not via this method.
390 *
391 * @return {@code true} if this {@code Subject}'s identity (aka {@link #getPrincipals() principals}) is
392 * remembered from a successful authentication during a previous session, {@code false} otherwise.
393 * @since 1.0
394 */
395 boolean isRemembered();
396
397 /**
398 * Returns the application {@code Session} associated with this Subject. If no session exists when this
399 * method is called, a new session will be created, associated with this Subject, and then returned.
400 *
401 * @return the application {@code Session} associated with this Subject.
402 * @see #getSession(boolean)
403 * @since 0.2
404 */
405 Session getSession();
406
407 /**
408 * Returns the application {@code Session} associated with this Subject. Based on the boolean argument,
409 * this method functions as follows:
410 * <ul>
411 * <li>If there is already an existing session associated with this {@code Subject}, it is returned and
412 * the {@code create} argument is ignored.</li>
413 * <li>If no session exists and {@code create} is {@code true}, a new session will be created, associated with
414 * this {@code Subject} and then returned.</li>
415 * <li>If no session exists and {@code create} is {@code false}, {@code null} is returned.</li>
416 * </ul>
417 *
418 * @param create boolean argument determining if a new session should be created or not if there is no existing session.
419 * @return the application {@code Session} associated with this {@code Subject} or {@code null} based
420 * on the above described logic.
421 * @since 0.2
422 */
423 Session getSession(boolean create);
424
425 /**
426 * Logs out this Subject and invalidates and/or removes any associated entities,
427 * such as a {@link Session Session} and authorization data. After this method is called, the Subject is
428 * considered 'anonymous' and may continue to be used for another log-in if desired.
429 * <h3>Web Environment Warning</h3>
430 * Calling this method in web environments will usually remove any associated session cookie as part of
431 * session invalidation. Because cookies are part of the HTTP header, and headers can only be set before the
432 * response body (html, image, etc.) is sent, this method in web environments must be called before <em>any</em>
433 * content has been rendered.
434 * <p/>
435 * The typical approach most applications use in this scenario is to redirect the user to a different
436 * location (e.g. home page) immediately after calling this method. This is an effect of the HTTP protocol
437 * itself and not a reflection of Shiro's implementation.
438 * <p/>
439 * Non-HTTP environments may of course use a logged-out subject for login again if desired.
440 */
441 void logout();
442
443 /**
444 * Associates the specified {@code Callable} with this {@code Subject} instance and then executes it on the
445 * currently running thread. If you want to execute the {@code Callable} on a different thread, it is better to
446 * use the {@link #associateWith(Callable)} method instead.
447 *
448 * @param callable the Callable to associate with this subject and then execute.
449 * @param <V> the type of return value the {@code Callable} will return
450 * @return the resulting object returned by the {@code Callable}'s execution.
451 * @throws ExecutionException if the {@code Callable}'s {@link Callable#call call} method throws an exception.
452 * @since 1.0
453 */
454 <V> V execute(Callable<V> callable) throws ExecutionException;
455
456 /**
457 * Associates the specified {@code Runnable} with this {@code Subject} instance and then executes it on the
458 * currently running thread. If you want to execute the {@code Runnable} on a different thread, it is better to
459 * use the {@link #associateWith(Runnable)} method instead.
460 * <p/>
461 * <b>Note</b>: This method is primarily provided to execute existing/legacy Runnable implementations. It is better
462 * for new code to use {@link #execute(Callable)} since that supports the ability to return values and catch
463 * exceptions.
464 *
465 * @param runnable the {@code Runnable} to associate with this {@code Subject} and then execute.
466 * @since 1.0
467 */
468 void execute(Runnable runnable);
469
470 /**
471 * Returns a {@code Callable} instance matching the given argument while additionally ensuring that it will
472 * retain and execute under this Subject's identity. The returned object can be used with an
473 * {@link java.util.concurrent.ExecutorService ExecutorService} to execute as this Subject.
474 * <p/>
475 * This will effectively ensure that any calls to
476 * {@code SecurityUtils}.{@link SecurityUtils#getSubject() getSubject()} and related functionality will continue
477 * to function properly on any thread that executes the returned {@code Callable} instance.
478 *
479 * @param callable the callable to execute as this {@code Subject}
480 * @param <V> the {@code Callable}s return value type
481 * @return a {@code Callable} that can be run as this {@code Subject}.
482 * @since 1.0
483 */
484 <V> Callable<V> associateWith(Callable<V> callable);
485
486 /**
487 * Returns a {@code Runnable} instance matching the given argument while additionally ensuring that it will
488 * retain and execute under this Subject's identity. The returned object can be used with an
489 * {@link java.util.concurrent.Executor Executor} or another thread to execute as this Subject.
490 * <p/>
491 * This will effectively ensure that any calls to
492 * {@code SecurityUtils}.{@link SecurityUtils#getSubject() getSubject()} and related functionality will continue
493 * to function properly on any thread that executes the returned {@code Runnable} instance.
494 * <p/>
495 * *Note that if you need a return value to be returned as a result of the runnable's execution or if you need to
496 * react to any Exceptions, it is highly recommended to use the
497 * {@link #associateWith(java.util.concurrent.Callable) createCallable} method instead of this one.
498 *
499 * @param runnable the runnable to execute as this {@code Subject}
500 * @return a {@code Runnable} that can be run as this {@code Subject} on another thread.
501 * @see #associateWith (java.util.concurrent.Callable)
502 * @since 1.0
503 */
504 Runnable associateWith(Runnable runnable);
505
506 /**
507 * Allows this subject to 'run as' or 'assume' another identity indefinitely. This can only be
508 * called when the {@code Subject} instance already has an identity (i.e. they are remembered from a previous
509 * log-in or they have authenticated during their current session).
510 * <p/>
511 * Some notes about {@code runAs}:
512 * <ul>
513 * <li>You can tell if a {@code Subject} is 'running as' another identity by calling the
514 * {@link #isRunAs() isRunAs()} method.</li>
515 * <li>If running as another identity, you can determine what the previous 'pre run as' identity
516 * was by calling the {@link #getPreviousPrincipals() getPreviousPrincipals()} method.</li>
517 * <li>When you want a {@code Subject} to stop running as another identity, you can return to its previous
518 * 'pre run as' identity by calling the {@link #releaseRunAs() releaseRunAs()} method.</li>
519 * </ul>
520 *
521 * @param principals the identity to 'run as', aka the identity to <em>assume</em> indefinitely.
522 * @throws NullPointerException if the specified principals collection is {@code null} or empty.
523 * @throws IllegalStateException if this {@code Subject} does not yet have an identity of its own.
524 * @since 1.0
525 */
526 void runAs(PrincipalCollection principals) throws NullPointerException, IllegalStateException;
527
528 /**
529 * Returns {@code true} if this {@code Subject} is 'running as' another identity other than its original one or
530 * {@code false} otherwise (normal {@code Subject} state). See the {@link #runAs runAs} method for more
531 * information.
532 *
533 * @return {@code true} if this {@code Subject} is 'running as' another identity other than its original one or
534 * {@code false} otherwise (normal {@code Subject} state).
535 * @see #runAs
536 * @since 1.0
537 */
538 boolean isRunAs();
539
540 /**
541 * Returns the previous 'pre run as' identity of this {@code Subject} before assuming the current
542 * {@link #runAs runAs} identity, or {@code null} if this {@code Subject} is not operating under an assumed
543 * identity (normal state). See the {@link #runAs runAs} method for more information.
544 *
545 * @return the previous 'pre run as' identity of this {@code Subject} before assuming the current
546 * {@link #runAs runAs} identity, or {@code null} if this {@code Subject} is not operating under an assumed
547 * identity (normal state).
548 * @see #runAs
549 * @since 1.0
550 */
551 PrincipalCollection getPreviousPrincipals();
552
553 /**
554 * Releases the current 'run as' (assumed) identity and reverts back to the previous 'pre run as'
555 * identity that existed before {@code #runAs runAs} was called.
556 * <p/>
557 * This method returns 'run as' (assumed) identity being released or {@code null} if this {@code Subject} is not
558 * operating under an assumed identity.
559 *
560 * @return the 'run as' (assumed) identity being released or {@code null} if this {@code Subject} is not operating
561 * under an assumed identity.
562 * @see #runAs
563 * @since 1.0
564 */
565 PrincipalCollection releaseRunAs();
566
567 /**
568 * Builder design pattern implementation for creating {@link Subject} instances in a simplified way without
569 * requiring knowledge of Shiro's construction techniques.
570 * <p/>
571 * <b>NOTE</b>: This is provided for framework development support only and should typically never be used by
572 * application developers. {@code Subject} instances should generally be acquired by using
573 * <code>SecurityUtils.{@link SecurityUtils#getSubject() getSubject()}</code>
574 * <h4>Usage</h4>
575 * The simplest usage of this builder is to construct an anonymous, session-less {@code Subject} instance:
576 * <pre>
577 * Subject subject = new Subject.{@link #Builder() Builder}().{@link #buildSubject() buildSubject()};</pre>
578 * The default, no-arg {@code Subject.Builder()} constructor shown above will use the application's
579 * currently accessible {@code SecurityManager} via
580 * <code>SecurityUtils.{@link SecurityUtils#getSecurityManager() getSecurityManager()}</code>. You may also
581 * specify the exact {@code SecurityManager} instance to be used by the additional
582 * <code>Subject.{@link #Builder(org.apache.shiro.mgt.SecurityManager) Builder(securityManager)}</code>
583 * constructor if desired.
584 * <p/>
585 * All other methods may be called before the {@link #buildSubject() buildSubject()} method to
586 * provide context on how to construct the {@code Subject} instance. For example, if you have a session id and
587 * want to acquire the {@code Subject} that 'owns' that session (assuming the session exists and is not expired):
588 * <pre>
589 * Subject subject = new Subject.Builder().sessionId(sessionId).buildSubject();</pre>
590 * <p/>
591 * Similarly, if you want a {@code Subject} instance reflecting a certain identity:
592 * <pre>
593 * PrincipalCollection principals = new SimplePrincipalCollection("username", <em>yourRealmName</em>);
594 * Subject subject = new Subject.Builder().principals(principals).build();</pre>
595 * <p/>
596 * <b>Note*</b> that the returned {@code Subject} instance is <b>not</b> automatically bound to the application (thread)
597 * for further use. That is,
598 * {@link org.apache.shiro.SecurityUtils SecurityUtils}.{@link org.apache.shiro.SecurityUtils#getSubject() getSubject()}
599 * will not automatically return the same instance as what is returned by the builder. It is up to the framework
600 * developer to bind the built {@code Subject} for continued use if desired.
601 *
602 * @since 1.0
603 */
604 class Builder {
605
606 /**
607 * Hold all contextual data via the Builder instance's method invocations to be sent to the
608 * {@code SecurityManager} during the {@link #buildSubject} call.
609 */
610 private final SubjectContext subjectContext;
611
612 /**
613 * The SecurityManager to invoke during the {@link #buildSubject} call.
614 */
615 private final SecurityManager securityManager;
616
617 /**
618 * Constructs a new {@link Subject.Builder} instance, using the {@code SecurityManager} instance available
619 * to the calling code as determined by a call to {@link org.apache.shiro.SecurityUtils#getSecurityManager()}
620 * to build the {@code Subject} instance.
621 */
622 public Builder() {
623 this(SecurityUtils.getSecurityManager());
624 }
625
626 /**
627 * Constructs a new {@link Subject.Builder} instance which will use the specified {@code SecurityManager} when
628 * building the {@code Subject} instance.
629 *
630 * @param securityManager the {@code SecurityManager} to use when building the {@code Subject} instance.
631 */
632 public Builder(SecurityManager securityManager) {
633 if (securityManager == null) {
634 throw new NullPointerException("SecurityManager method argument cannot be null.");
635 }
636 this.securityManager = securityManager;
637 this.subjectContext = newSubjectContextInstance();
638 if (this.subjectContext == null) {
639 throw new IllegalStateException("Subject instance returned from 'newSubjectContextInstance' "
640 + "cannot be null.");
641 }
642 this.subjectContext.setSecurityManager(securityManager);
643 }
644
645 /**
646 * Creates a new {@code SubjectContext} instance to be used to populate with subject contextual data that
647 * will then be sent to the {@code SecurityManager} to create a new {@code Subject} instance.
648 *
649 * @return a new {@code SubjectContext} instance
650 */
651 protected SubjectContext newSubjectContextInstance() {
652 return new DefaultSubjectContext();
653 }
654
655 /**
656 * Returns the backing context used to build the {@code Subject} instance, available to subclasses
657 * since the {@code context} class attribute is marked as {@code private}.
658 *
659 * @return the backing context used to build the {@code Subject} instance, available to subclasses.
660 */
661 protected SubjectContext getSubjectContext() {
662 return this.subjectContext;
663 }
664
665 /**
666 * Enables building a {@link Subject Subject} instance that owns the {@link Session Session} with the
667 * specified {@code sessionId}.
668 * <p/>
669 * Usually when specifying a {@code sessionId}, no other {@code Builder} methods would be specified because
670 * everything else (principals, inet address, etc.) can usually be reconstructed based on the referenced
671 * session alone. In other words, this is almost always sufficient:
672 * <pre>
673 * new Subject.Builder().sessionId(sessionId).buildSubject();</pre>
674 * <p/>
675 * <b>Although simple in concept, this method provides very powerful functionality previously absent in almost
676 * all Java environments:</b>
677 * <p/>
678 * The ability to reference a {@code Subject} and their server-side session
679 * <em>across clients of different mediums</em> such as web applications, Java applets,
680 * standalone C# clients over XML-RPC and/or SOAP, and many others. This is a <em>huge</em>
681 * benefit in heterogeneous enterprise applications.
682 * <p/>
683 * To maintain session integrity across client mediums, the {@code sessionId} <b>must</b> be transmitted
684 * to all client mediums securely (e.g. over SSL) to prevent man-in-the-middle attacks. This
685 * is nothing new - all web applications are susceptible to the same problem when transmitting
686 * {@code Cookie}s or when using URL rewriting. As long as the
687 * {@code sessionId} is transmitted securely, session integrity can be maintained.
688 *
689 * @param sessionId the id of the session that backs the desired Subject being acquired.
690 * @return this {@code Builder} instance for method chaining.
691 */
692 public Builder sessionId(Serializable sessionId) {
693 if (sessionId != null) {
694 this.subjectContext.setSessionId(sessionId);
695 }
696 return this;
697 }
698
699 /**
700 * Ensures the {@code Subject} being built will reflect the specified host name or IP as its originating
701 * location.
702 *
703 * @param host the host name or IP address to use as the {@code Subject}'s originating location.
704 * @return this {@code Builder} instance for method chaining.
705 */
706 public Builder host(String host) {
707 if (StringUtils.hasText(host)) {
708 this.subjectContext.setHost(host);
709 }
710 return this;
711 }
712
713 /**
714 * Ensures the {@code Subject} being built will use the specified {@link Session} instance. Note that it is
715 * more common to use the {@link #sessionId sessionId} builder method rather than having to construct a
716 * {@code Session} instance for this method.
717 *
718 * @param session the session to use as the {@code Subject}'s {@link Session}
719 * @return this {@code Builder} instance for method chaining.
720 */
721 public Builder session(Session session) {
722 if (session != null) {
723 this.subjectContext.setSession(session);
724 }
725 return this;
726 }
727
728 /**
729 * Ensures the {@code Subject} being built will reflect the specified principals (aka identity).
730 * <p/>
731 * For example, if your application's unique identifier for users is a {@code String} username, and you wanted
732 * to create a {@code Subject} instance that reflected a user whose username is
733 * '{@code jsmith}', and you knew the Realm that could acquire {@code jsmith}'s principals based on the username
734 * was named "{@code myRealm}", you might create the '{@code jsmith} {@code Subject} instance this
735 * way:
736 * <pre>
737 * PrincipalCollection identity = new {@link SimplePrincipalCollection#SimplePrincipalCollection(Object, String)
738 * SimplePrincipalCollection}("jsmith", "myRealm");
739 * Subject jsmith = new Subject.Builder().principals(identity).buildSubject();</pre>
740 * <p/>
741 * Similarly, if your application's unique identifier for users is a {@code long} value (such as might be used
742 * as a primary key in a relational database) and you were using a {@code JDBC}
743 * {@code Realm} named, (unimaginatively) "jdbcRealm", you might create the Subject
744 * instance this way:
745 * <pre>
746 * long userId = //get user ID from somewhere
747 * PrincipalCollection userIdentity = new {@link SimplePrincipalCollection#SimplePrincipalCollection(Object, String)
748 * SimplePrincipalCollection}(<em>userId</em>, "jdbcRealm");
749 * Subject user = new Subject.Builder().principals(identity).buildSubject();</pre>
750 *
751 * @param principals the principals to use as the {@code Subject}'s identity.
752 * @return this {@code Builder} instance for method chaining.
753 */
754 public Builder principals(PrincipalCollection principals) {
755 if (principals != null && !principals.isEmpty()) {
756 this.subjectContext.setPrincipals(principals);
757 }
758 return this;
759 }
760
761 /**
762 * Configures whether or not the created Subject instance can create a new {@code Session} if one does not
763 * already exist. If set to {@code false}, any application calls to
764 * {@code subject.getSession()} or {@code subject.getSession(true))} will result in a SessionException.
765 * <p/>
766 * This setting is {@code true} by default, as most applications find value in sessions.
767 *
768 * @param enabled whether or not the created Subject instance can create a new {@code Session} if one does not
769 * already exist.
770 * @return this {@code Builder} instance for method chaining.
771 * @since 1.2
772 */
773 public Builder sessionCreationEnabled(boolean enabled) {
774 this.subjectContext.setSessionCreationEnabled(enabled);
775 return this;
776 }
777
778 /**
779 * Ensures the {@code Subject} being built will be considered
780 * {@link org.apache.shiro.subject.Subject#isAuthenticated() authenticated}. Per the
781 * {@link org.apache.shiro.subject.Subject#isAuthenticated() isAuthenticated()} JavaDoc, be careful
782 * when specifying {@code true} - you should know what you are doing and have a good reason for ignoring Shiro's
783 * default authentication state mechanisms.
784 *
785 * @param authenticated whether or not the built {@code Subject} will be considered authenticated.
786 * @return this {@code Builder} instance for method chaining.
787 * @see org.apache.shiro.subject.Subject#isAuthenticated()
788 */
789 public Builder authenticated(boolean authenticated) {
790 this.subjectContext.setAuthenticated(authenticated);
791 return this;
792 }
793
794 /**
795 * Allows custom attributes to be added to the underlying context {@code Map} used to construct the
796 * {@link Subject} instance.
797 * <p/>
798 * A {@code null} key throws an {@link IllegalArgumentException}. A {@code null} value effectively removes
799 * any previously stored attribute under the given key from the context map.
800 * <p/>
801 * <b>*NOTE*:</b> This method is only useful when configuring Shiro with a custom {@link SubjectFactory}
802 * implementation. This method allows end-users to append additional data to the context map which the
803 * {@code SubjectFactory} implementation can use when building custom Subject instances. As such, this method
804 * is only useful when a custom {@code SubjectFactory} implementation has been configured.
805 *
806 * @param attributeKey the key under which the corresponding value will be stored in the context {@code Map}.
807 * @param attributeValue the value to store in the context map under the specified {@code attributeKey}.
808 * @return this {@code Builder} instance for method chaining.
809 * @throws IllegalArgumentException if the {@code attributeKey} is {@code null}.
810 * @see SubjectFactory#createSubject(SubjectContext)
811 */
812 public Builder contextAttribute(String attributeKey, Object attributeValue) {
813 if (attributeKey == null) {
814 String msg = "Subject context map key cannot be null.";
815 throw new IllegalArgumentException(msg);
816 }
817 if (attributeValue == null) {
818 this.subjectContext.remove(attributeKey);
819 } else {
820 this.subjectContext.put(attributeKey, attributeValue);
821 }
822 return this;
823 }
824
825 /**
826 * Creates and returns a new {@code Subject} instance reflecting the cumulative state acquired by the
827 * other methods in this class.
828 * <p/>
829 * This {@code Builder} instance will still retain the underlying state after this method is called - it
830 * will not clear it; repeated calls to this method will return multiple {@link Subject} instances, all
831 * reflecting the exact same state. If a new (different) {@code Subject} is to be constructed, a new
832 * {@code Builder} instance must be created.
833 * <p/>
834 * <b>Note</b> that the returned {@code Subject} instance is <b>not</b> automatically bound to the application
835 * (thread) for further use. That is,
836 * {@link org.apache.shiro.SecurityUtils SecurityUtils}.{@link org.apache.shiro.SecurityUtils#getSubject() getSubject()}
837 * will not automatically return the same instance as what is returned by the builder. It is up to the
838 * framework developer to bind the returned {@code Subject} for continued use if desired.
839 *
840 * @return a new {@code Subject} instance reflecting the cumulative state acquired by the
841 * other methods in this class.
842 */
843 public Subject buildSubject() {
844 return this.securityManager.createSubject(this.subjectContext);
845 }
846 }
847
848 }