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