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