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