Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ModularRealmAuthorizer |
|
| 3.4074074074074074;3.407 |
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.authz; | |
20 | ||
21 | import org.apache.shiro.authz.permission.PermissionResolver; | |
22 | import org.apache.shiro.authz.permission.PermissionResolverAware; | |
23 | import org.apache.shiro.authz.permission.RolePermissionResolver; | |
24 | import org.apache.shiro.authz.permission.RolePermissionResolverAware; | |
25 | import org.apache.shiro.realm.Realm; | |
26 | import org.apache.shiro.subject.PrincipalCollection; | |
27 | ||
28 | import java.util.Collection; | |
29 | import java.util.List; | |
30 | ||
31 | ||
32 | /** | |
33 | * A <tt>ModularRealmAuthorizer</tt> is an <tt>Authorizer</tt> implementation that consults one or more configured | |
34 | * {@link Realm Realm}s during an authorization operation. | |
35 | * | |
36 | * @since 0.2 | |
37 | */ | |
38 | public class ModularRealmAuthorizer implements Authorizer, PermissionResolverAware, RolePermissionResolverAware { | |
39 | ||
40 | /** | |
41 | * The realms to consult during any authorization check. | |
42 | */ | |
43 | protected Collection<Realm> realms; | |
44 | ||
45 | /** | |
46 | * A PermissionResolver to be used by <em>all</em> configured realms. Leave <code>null</code> if you wish | |
47 | * to configure different resolvers for different realms. | |
48 | */ | |
49 | protected PermissionResolver permissionResolver; | |
50 | ||
51 | /** | |
52 | * A RolePermissionResolver to be used by <em>all</em> configured realms. Leave <code>null</code> if you wish | |
53 | * to configure different resolvers for different realms. | |
54 | */ | |
55 | protected RolePermissionResolver rolePermissionResolver; | |
56 | ||
57 | /** | |
58 | * Default no-argument constructor, does nothing. | |
59 | */ | |
60 | 37 | public ModularRealmAuthorizer() { |
61 | 37 | } |
62 | ||
63 | /** | |
64 | * Constructor that accepts the <code>Realm</code>s to consult during an authorization check. Immediately calls | |
65 | * {@link #setRealms setRealms(realms)}. | |
66 | * | |
67 | * @param realms the realms to consult during an authorization check. | |
68 | */ | |
69 | 0 | public ModularRealmAuthorizer(Collection<Realm> realms) { |
70 | 0 | setRealms(realms); |
71 | 0 | } |
72 | ||
73 | /** | |
74 | * Returns the realms wrapped by this <code>Authorizer</code> which are consulted during an authorization check. | |
75 | * | |
76 | * @return the realms wrapped by this <code>Authorizer</code> which are consulted during an authorization check. | |
77 | */ | |
78 | public Collection<Realm> getRealms() { | |
79 | 115 | return this.realms; |
80 | } | |
81 | ||
82 | /** | |
83 | * Sets the realms wrapped by this <code>Authorizer</code> which are consulted during an authorization check. | |
84 | * | |
85 | * @param realms the realms wrapped by this <code>Authorizer</code> which are consulted during an authorization check. | |
86 | */ | |
87 | public void setRealms(Collection<Realm> realms) { | |
88 | 34 | this.realms = realms; |
89 | 34 | applyPermissionResolverToRealms(); |
90 | 34 | applyRolePermissionResolverToRealms(); |
91 | 34 | } |
92 | ||
93 | /** | |
94 | * Returns the PermissionResolver to be used on <em>all</em> configured realms, or <code>null</code (the default) | |
95 | * if all realm instances will each configure their own permission resolver. | |
96 | * | |
97 | * @return the PermissionResolver to be used on <em>all</em> configured realms, or <code>null</code (the default) | |
98 | * if realm instances will each configure their own permission resolver. | |
99 | * @since 1.0 | |
100 | */ | |
101 | public PermissionResolver getPermissionResolver() { | |
102 | 34 | return this.permissionResolver; |
103 | } | |
104 | ||
105 | /** | |
106 | * Sets the specified {@link PermissionResolver PermissionResolver} on <em>all</em> of the wrapped realms that | |
107 | * implement the {@link org.apache.shiro.authz.permission.PermissionResolverAware PermissionResolverAware} interface. | |
108 | * <p/> | |
109 | * Only call this method if you want the permission resolver to be passed to all realms that implement the | |
110 | * <code>PermissionResolver</code> interface. If you do not want this to occur, the realms must | |
111 | * configure themselves individually (or be configured individually). | |
112 | * | |
113 | * @param permissionResolver the permissionResolver to set on all of the wrapped realms that implement the | |
114 | * {@link org.apache.shiro.authz.permission.PermissionResolverAware PermissionResolverAware} interface. | |
115 | */ | |
116 | public void setPermissionResolver(PermissionResolver permissionResolver) { | |
117 | 0 | this.permissionResolver = permissionResolver; |
118 | 0 | applyPermissionResolverToRealms(); |
119 | 0 | } |
120 | ||
121 | /** | |
122 | * Sets the internal {@link #getPermissionResolver} on any internal configured | |
123 | * {@link #getRealms Realms} that implement the {@link org.apache.shiro.authz.permission.PermissionResolverAware PermissionResolverAware} interface. | |
124 | * <p/> | |
125 | * This method is called after setting a permissionResolver on this ModularRealmAuthorizer via the | |
126 | * {@link #setPermissionResolver(org.apache.shiro.authz.permission.PermissionResolver) setPermissionResolver} method. | |
127 | * <p/> | |
128 | * It is also called after setting one or more realms via the {@link #setRealms setRealms} method to allow these | |
129 | * newly available realms to be given the <code>PermissionResolver</code> already in use. | |
130 | * | |
131 | * @since 1.0 | |
132 | */ | |
133 | protected void applyPermissionResolverToRealms() { | |
134 | 34 | PermissionResolver resolver = getPermissionResolver(); |
135 | 34 | Collection<Realm> realms = getRealms(); |
136 | 34 | if (resolver != null && realms != null && !realms.isEmpty()) { |
137 | 0 | for (Realm realm : realms) { |
138 | 0 | if (realm instanceof PermissionResolverAware) { |
139 | 0 | ((PermissionResolverAware) realm).setPermissionResolver(resolver); |
140 | } | |
141 | 0 | } |
142 | } | |
143 | 34 | } |
144 | ||
145 | /** | |
146 | * Returns the RolePermissionResolver to be used on <em>all</em> configured realms, or <code>null</code (the default) | |
147 | * if all realm instances will each configure their own permission resolver. | |
148 | * | |
149 | * @return the RolePermissionResolver to be used on <em>all</em> configured realms, or <code>null</code (the default) | |
150 | * if realm instances will each configure their own role permission resolver. | |
151 | * @since 1.0 | |
152 | */ | |
153 | public RolePermissionResolver getRolePermissionResolver() { | |
154 | 35 | return this.rolePermissionResolver; |
155 | } | |
156 | ||
157 | /** | |
158 | * Sets the specified {@link RolePermissionResolver RolePermissionResolver} on <em>all</em> of the wrapped realms that | |
159 | * implement the {@link org.apache.shiro.authz.permission.RolePermissionResolverAware PermissionResolverAware} interface. | |
160 | * <p/> | |
161 | * Only call this method if you want the permission resolver to be passed to all realms that implement the | |
162 | * <code>RolePermissionResolver</code> interface. If you do not want this to occur, the realms must | |
163 | * configure themselves individually (or be configured individually). | |
164 | * | |
165 | * @param rolePermissionResolver the rolePermissionResolver to set on all of the wrapped realms that implement the | |
166 | * {@link org.apache.shiro.authz.permission.RolePermissionResolverAware RolePermissionResolverAware} interface. | |
167 | */ | |
168 | public void setRolePermissionResolver(RolePermissionResolver rolePermissionResolver) { | |
169 | 1 | this.rolePermissionResolver = rolePermissionResolver; |
170 | 1 | applyRolePermissionResolverToRealms(); |
171 | 1 | } |
172 | ||
173 | ||
174 | /** | |
175 | * Sets the internal {@link #getRolePermissionResolver} on any internal configured | |
176 | * {@link #getRealms Realms} that implement the {@link org.apache.shiro.authz.permission.RolePermissionResolverAware RolePermissionResolverAware} interface. | |
177 | * <p/> | |
178 | * This method is called after setting a rolePermissionResolver on this ModularRealmAuthorizer via the | |
179 | * {@link #setRolePermissionResolver(org.apache.shiro.authz.permission.RolePermissionResolver) setRolePermissionResolver} method. | |
180 | * <p/> | |
181 | * It is also called after setting one or more realms via the {@link #setRealms setRealms} method to allow these | |
182 | * newly available realms to be given the <code>RolePermissionResolver</code> already in use. | |
183 | * | |
184 | * @since 1.0 | |
185 | */ | |
186 | protected void applyRolePermissionResolverToRealms() { | |
187 | 35 | RolePermissionResolver resolver = getRolePermissionResolver(); |
188 | 35 | Collection<Realm> realms = getRealms(); |
189 | 35 | if (resolver != null && realms != null && !realms.isEmpty()) { |
190 | 2 | for (Realm realm : realms) { |
191 | 5 | if (realm instanceof RolePermissionResolverAware) { |
192 | 5 | ((RolePermissionResolverAware) realm).setRolePermissionResolver(resolver); |
193 | } | |
194 | 5 | } |
195 | } | |
196 | 35 | } |
197 | ||
198 | ||
199 | /** | |
200 | * Used by the {@link Authorizer Authorizer} implementation methods to ensure that the {@link #setRealms realms} | |
201 | * has been set. The default implementation ensures the property is not null and not empty. | |
202 | * | |
203 | * @throws IllegalStateException if the <tt>realms</tt> property is configured incorrectly. | |
204 | */ | |
205 | protected void assertRealmsConfigured() throws IllegalStateException { | |
206 | 23 | Collection<Realm> realms = getRealms(); |
207 | 23 | if (realms == null || realms.isEmpty()) { |
208 | 0 | String msg = "Configuration error: No realms have been configured! One or more realms must be " + |
209 | "present to execute an authorization operation."; | |
210 | 0 | throw new IllegalStateException(msg); |
211 | } | |
212 | 23 | } |
213 | ||
214 | /** | |
215 | * Returns <code>true</code> if any of the configured realms' | |
216 | * {@link #isPermitted(org.apache.shiro.subject.PrincipalCollection, String)} returns <code>true</code>, | |
217 | * <code>false</code> otherwise. | |
218 | */ | |
219 | public boolean isPermitted(PrincipalCollection principals, String permission) { | |
220 | 2 | assertRealmsConfigured(); |
221 | 2 | for (Realm realm : getRealms()) { |
222 | 2 | if (!(realm instanceof Authorizer)) continue; |
223 | 2 | if (((Authorizer) realm).isPermitted(principals, permission)) { |
224 | 1 | return true; |
225 | } | |
226 | 1 | } |
227 | 1 | return false; |
228 | } | |
229 | ||
230 | /** | |
231 | * Returns <code>true</code> if any of the configured realms' | |
232 | * {@link #isPermitted(org.apache.shiro.subject.PrincipalCollection, Permission)} call returns <code>true</code>, | |
233 | * <code>false</code> otherwise. | |
234 | */ | |
235 | public boolean isPermitted(PrincipalCollection principals, Permission permission) { | |
236 | 0 | assertRealmsConfigured(); |
237 | 0 | for (Realm realm : getRealms()) { |
238 | 0 | if (!(realm instanceof Authorizer)) continue; |
239 | 0 | if (((Authorizer) realm).isPermitted(principals, permission)) { |
240 | 0 | return true; |
241 | } | |
242 | 0 | } |
243 | 0 | return false; |
244 | } | |
245 | ||
246 | /** | |
247 | * Returns <code>true</code> if any of the configured realms' | |
248 | * {@link #isPermittedAll(org.apache.shiro.subject.PrincipalCollection, String...)} call returns | |
249 | * <code>true</code>, <code>false</code> otherwise. | |
250 | */ | |
251 | public boolean[] isPermitted(PrincipalCollection principals, String... permissions) { | |
252 | 0 | assertRealmsConfigured(); |
253 | 0 | if (permissions != null && permissions.length > 0) { |
254 | 0 | boolean[] isPermitted = new boolean[permissions.length]; |
255 | 0 | for (int i = 0; i < permissions.length; i++) { |
256 | 0 | isPermitted[i] = isPermitted(principals, permissions[i]); |
257 | } | |
258 | 0 | return isPermitted; |
259 | } | |
260 | 0 | return new boolean[0]; |
261 | } | |
262 | ||
263 | /** | |
264 | * Returns <code>true</code> if any of the configured realms' | |
265 | * {@link #isPermitted(org.apache.shiro.subject.PrincipalCollection, List)} call returns <code>true</code>, | |
266 | * <code>false</code> otherwise. | |
267 | */ | |
268 | public boolean[] isPermitted(PrincipalCollection principals, List<Permission> permissions) { | |
269 | 0 | assertRealmsConfigured(); |
270 | 0 | if (permissions != null && !permissions.isEmpty()) { |
271 | 0 | boolean[] isPermitted = new boolean[permissions.size()]; |
272 | 0 | int i = 0; |
273 | 0 | for (Permission p : permissions) { |
274 | 0 | isPermitted[i++] = isPermitted(principals, p); |
275 | 0 | } |
276 | 0 | return isPermitted; |
277 | } | |
278 | ||
279 | 0 | return new boolean[0]; |
280 | } | |
281 | ||
282 | /** | |
283 | * Returns <code>true</code> if any of the configured realms' | |
284 | * {@link #isPermitted(org.apache.shiro.subject.PrincipalCollection, String)} call returns <code>true</code> | |
285 | * for <em>all</em> of the specified string permissions, <code>false</code> otherwise. | |
286 | */ | |
287 | public boolean isPermittedAll(PrincipalCollection principals, String... permissions) { | |
288 | 0 | assertRealmsConfigured(); |
289 | 0 | if (permissions != null && permissions.length > 0) { |
290 | 0 | for (String perm : permissions) { |
291 | 0 | if (!isPermitted(principals, perm)) { |
292 | 0 | return false; |
293 | } | |
294 | } | |
295 | } | |
296 | 0 | return true; |
297 | } | |
298 | ||
299 | /** | |
300 | * Returns <code>true</code> if any of the configured realms' | |
301 | * {@link #isPermitted(org.apache.shiro.subject.PrincipalCollection, Permission)} call returns <code>true</code> | |
302 | * for <em>all</em> of the specified Permissions, <code>false</code> otherwise. | |
303 | */ | |
304 | public boolean isPermittedAll(PrincipalCollection principals, Collection<Permission> permissions) { | |
305 | 0 | assertRealmsConfigured(); |
306 | 0 | if (permissions != null && !permissions.isEmpty()) { |
307 | 0 | for (Permission permission : permissions) { |
308 | 0 | if (!isPermitted(principals, permission)) { |
309 | 0 | return false; |
310 | } | |
311 | 0 | } |
312 | } | |
313 | 0 | return true; |
314 | } | |
315 | ||
316 | /** | |
317 | * If !{@link #isPermitted(org.apache.shiro.subject.PrincipalCollection, String) isPermitted(permission)}, throws | |
318 | * an <code>UnauthorizedException</code> otherwise returns quietly. | |
319 | */ | |
320 | public void checkPermission(PrincipalCollection principals, String permission) throws AuthorizationException { | |
321 | 0 | assertRealmsConfigured(); |
322 | 0 | if (!isPermitted(principals, permission)) { |
323 | 0 | throw new UnauthorizedException("Subject does not have permission [" + permission + "]"); |
324 | } | |
325 | 0 | } |
326 | ||
327 | /** | |
328 | * If !{@link #isPermitted(org.apache.shiro.subject.PrincipalCollection, Permission) isPermitted(permission)}, throws | |
329 | * an <code>UnauthorizedException</code> otherwise returns quietly. | |
330 | */ | |
331 | public void checkPermission(PrincipalCollection principals, Permission permission) throws AuthorizationException { | |
332 | 0 | assertRealmsConfigured(); |
333 | 0 | if (!isPermitted(principals, permission)) { |
334 | 0 | throw new UnauthorizedException("Subject does not have permission [" + permission + "]"); |
335 | } | |
336 | 0 | } |
337 | ||
338 | /** | |
339 | * If !{@link #isPermitted(org.apache.shiro.subject.PrincipalCollection, String...) isPermitted(permission)}, | |
340 | * throws an <code>UnauthorizedException</code> otherwise returns quietly. | |
341 | */ | |
342 | public void checkPermissions(PrincipalCollection principals, String... permissions) throws AuthorizationException { | |
343 | 0 | assertRealmsConfigured(); |
344 | 0 | if (permissions != null && permissions.length > 0) { |
345 | 0 | for (String perm : permissions) { |
346 | 0 | checkPermission(principals, perm); |
347 | } | |
348 | } | |
349 | 0 | } |
350 | ||
351 | /** | |
352 | * If !{@link #isPermitted(org.apache.shiro.subject.PrincipalCollection, Permission) isPermitted(permission)} for | |
353 | * <em>all</em> the given Permissions, throws | |
354 | * an <code>UnauthorizedException</code> otherwise returns quietly. | |
355 | */ | |
356 | public void checkPermissions(PrincipalCollection principals, Collection<Permission> permissions) throws AuthorizationException { | |
357 | 0 | assertRealmsConfigured(); |
358 | 0 | if (permissions != null) { |
359 | 0 | for (Permission permission : permissions) { |
360 | 0 | checkPermission(principals, permission); |
361 | 0 | } |
362 | } | |
363 | 0 | } |
364 | ||
365 | /** | |
366 | * Returns <code>true</code> if any of the configured realms' | |
367 | * {@link #hasRole(org.apache.shiro.subject.PrincipalCollection, String)} call returns <code>true</code>, | |
368 | * <code>false</code> otherwise. | |
369 | */ | |
370 | public boolean hasRole(PrincipalCollection principals, String roleIdentifier) { | |
371 | 21 | assertRealmsConfigured(); |
372 | 21 | for (Realm realm : getRealms()) { |
373 | 21 | if (!(realm instanceof Authorizer)) continue; |
374 | 21 | if (((Authorizer) realm).hasRole(principals, roleIdentifier)) { |
375 | 10 | return true; |
376 | } | |
377 | 11 | } |
378 | 11 | return false; |
379 | } | |
380 | ||
381 | /** | |
382 | * Calls {@link #hasRole(org.apache.shiro.subject.PrincipalCollection, String)} for each role name in the specified | |
383 | * collection and places the return value from each call at the respective location in the returned array. | |
384 | */ | |
385 | public boolean[] hasRoles(PrincipalCollection principals, List<String> roleIdentifiers) { | |
386 | 0 | assertRealmsConfigured(); |
387 | 0 | if (roleIdentifiers != null && !roleIdentifiers.isEmpty()) { |
388 | 0 | boolean[] hasRoles = new boolean[roleIdentifiers.size()]; |
389 | 0 | int i = 0; |
390 | 0 | for (String roleId : roleIdentifiers) { |
391 | 0 | hasRoles[i++] = hasRole(principals, roleId); |
392 | 0 | } |
393 | 0 | return hasRoles; |
394 | } | |
395 | ||
396 | 0 | return new boolean[0]; |
397 | } | |
398 | ||
399 | /** | |
400 | * Returns <code>true</code> iff any of the configured realms' | |
401 | * {@link #hasRole(org.apache.shiro.subject.PrincipalCollection, String)} call returns <code>true</code> for | |
402 | * <em>all</em> roles specified, <code>false</code> otherwise. | |
403 | */ | |
404 | public boolean hasAllRoles(PrincipalCollection principals, Collection<String> roleIdentifiers) { | |
405 | 0 | assertRealmsConfigured(); |
406 | 0 | for (String roleIdentifier : roleIdentifiers) { |
407 | 0 | if (!hasRole(principals, roleIdentifier)) { |
408 | 0 | return false; |
409 | } | |
410 | 0 | } |
411 | 0 | return true; |
412 | } | |
413 | ||
414 | /** | |
415 | * If !{@link #hasRole(org.apache.shiro.subject.PrincipalCollection, String) hasRole(role)}, throws | |
416 | * an <code>UnauthorizedException</code> otherwise returns quietly. | |
417 | */ | |
418 | public void checkRole(PrincipalCollection principals, String role) throws AuthorizationException { | |
419 | 0 | assertRealmsConfigured(); |
420 | 0 | if (!hasRole(principals, role)) { |
421 | 0 | throw new UnauthorizedException("Subject does not have role [" + role + "]"); |
422 | } | |
423 | 0 | } |
424 | ||
425 | /** | |
426 | * Calls {@link #checkRoles(PrincipalCollection principals, String... roles) checkRoles(PrincipalCollection principals, String... roles) }. | |
427 | */ | |
428 | public void checkRoles(PrincipalCollection principals, Collection<String> roles) throws AuthorizationException { | |
429 | //SHIRO-234 - roles.toArray() -> roles.toArray(new String[roles.size()]) | |
430 | 0 | if (roles != null && !roles.isEmpty()) checkRoles(principals, roles.toArray(new String[roles.size()])); |
431 | 0 | } |
432 | ||
433 | /** | |
434 | * Calls {@link #checkRole(org.apache.shiro.subject.PrincipalCollection, String) checkRole} for each role specified. | |
435 | */ | |
436 | public void checkRoles(PrincipalCollection principals, String... roles) throws AuthorizationException { | |
437 | 0 | assertRealmsConfigured(); |
438 | 0 | if (roles != null) { |
439 | 0 | for (String role : roles) { |
440 | 0 | checkRole(principals, role); |
441 | } | |
442 | } | |
443 | 0 | } |
444 | } |