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