1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.shiro.realm;
20
21 import org.apache.shiro.authc.credential.CredentialsMatcher;
22 import org.apache.shiro.authz.*;
23 import org.apache.shiro.authz.permission.*;
24 import org.apache.shiro.cache.Cache;
25 import org.apache.shiro.cache.CacheManager;
26 import org.apache.shiro.subject.PrincipalCollection;
27 import org.apache.shiro.util.CollectionUtils;
28 import org.apache.shiro.util.Initializable;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 import java.util.*;
33 import java.util.concurrent.atomic.AtomicInteger;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public abstract class AuthorizingRealm extends AuthenticatingRealm
56 implements Authorizer, Initializable, PermissionResolverAware, RolePermissionResolverAware {
57
58
59
60
61
62
63 private static final Logger log = LoggerFactory.getLogger(AuthorizingRealm.class);
64
65
66
67
68 private static final String DEFAULT_AUTHORIZATION_CACHE_SUFFIX = ".authorizationCache";
69
70 private static final AtomicInteger INSTANCE_COUNT = new AtomicInteger();
71
72
73
74
75
76
77
78 private boolean authorizationCachingEnabled;
79 private Cache<Object, AuthorizationInfo> authorizationCache;
80 private String authorizationCacheName;
81
82 private PermissionResolver permissionResolver;
83
84 private RolePermissionResolver permissionRoleResolver;
85
86
87
88
89
90 public AuthorizingRealm() {
91 this(null, null);
92 }
93
94 public AuthorizingRealm(CacheManager cacheManager) {
95 this(cacheManager, null);
96 }
97
98 public AuthorizingRealm(CredentialsMatcher matcher) {
99 this(null, matcher);
100 }
101
102 public AuthorizingRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
103 super();
104 if (cacheManager != null) setCacheManager(cacheManager);
105 if (matcher != null) setCredentialsMatcher(matcher);
106
107 this.authorizationCachingEnabled = true;
108 this.permissionResolver = new WildcardPermissionResolver();
109
110 int instanceNumber = INSTANCE_COUNT.getAndIncrement();
111 this.authorizationCacheName = getClass().getName() + DEFAULT_AUTHORIZATION_CACHE_SUFFIX;
112 if (instanceNumber > 0) {
113 this.authorizationCacheName = this.authorizationCacheName + "." + instanceNumber;
114 }
115 }
116
117
118
119
120
121 public void setName(String name) {
122 super.setName(name);
123 String authzCacheName = this.authorizationCacheName;
124 if (authzCacheName != null && authzCacheName.startsWith(getClass().getName())) {
125
126
127 this.authorizationCacheName = name + DEFAULT_AUTHORIZATION_CACHE_SUFFIX;
128 }
129 }
130
131 public void setAuthorizationCache(Cache<Object, AuthorizationInfo> authorizationCache) {
132 this.authorizationCache = authorizationCache;
133 }
134
135 public Cache<Object, AuthorizationInfo> getAuthorizationCache() {
136 return this.authorizationCache;
137 }
138
139 public String getAuthorizationCacheName() {
140 return authorizationCacheName;
141 }
142
143 @SuppressWarnings({"UnusedDeclaration"})
144 public void setAuthorizationCacheName(String authorizationCacheName) {
145 this.authorizationCacheName = authorizationCacheName;
146 }
147
148
149
150
151
152
153
154
155
156 public boolean isAuthorizationCachingEnabled() {
157 return isCachingEnabled() && authorizationCachingEnabled;
158 }
159
160
161
162
163
164
165
166
167
168 @SuppressWarnings({"UnusedDeclaration"})
169 public void setAuthorizationCachingEnabled(boolean authenticationCachingEnabled) {
170 this.authorizationCachingEnabled = authenticationCachingEnabled;
171 if (authenticationCachingEnabled) {
172 setCachingEnabled(true);
173 }
174 }
175
176 public PermissionResolver getPermissionResolver() {
177 return permissionResolver;
178 }
179
180 public void setPermissionResolver(PermissionResolver permissionResolver) {
181 if (permissionResolver == null) throw new IllegalArgumentException("Null PermissionResolver is not allowed");
182 this.permissionResolver = permissionResolver;
183 }
184
185 public RolePermissionResolver getRolePermissionResolver() {
186 return permissionRoleResolver;
187 }
188
189 public void setRolePermissionResolver(RolePermissionResolver permissionRoleResolver) {
190 this.permissionRoleResolver = permissionRoleResolver;
191 }
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217 protected void onInit() {
218 super.onInit();
219
220 getAvailableAuthorizationCache();
221 }
222
223 protected void afterCacheManagerSet() {
224 super.afterCacheManagerSet();
225
226 getAvailableAuthorizationCache();
227 }
228
229 private Cache<Object, AuthorizationInfo> getAuthorizationCacheLazy() {
230
231 if (this.authorizationCache == null) {
232
233 if (log.isDebugEnabled()) {
234 log.debug("No authorizationCache instance set. Checking for a cacheManager...");
235 }
236
237 CacheManager cacheManager = getCacheManager();
238
239 if (cacheManager != null) {
240 String cacheName = getAuthorizationCacheName();
241 if (log.isDebugEnabled()) {
242 log.debug("CacheManager [" + cacheManager + "] has been configured. Building " +
243 "authorization cache named [" + cacheName + "]");
244 }
245 this.authorizationCache = cacheManager.getCache(cacheName);
246 } else {
247 if (log.isDebugEnabled()) {
248 log.debug("No cache or cacheManager properties have been set. Authorization cache cannot " +
249 "be obtained.");
250 }
251 }
252 }
253
254 return this.authorizationCache;
255 }
256
257 private Cache<Object, AuthorizationInfo> getAvailableAuthorizationCache() {
258 Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
259 if (cache == null && isAuthorizationCachingEnabled()) {
260 cache = getAuthorizationCacheLazy();
261 }
262 return cache;
263 }
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310 protected AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {
311
312 if (principals == null) {
313 return null;
314 }
315
316 AuthorizationInfo info = null;
317
318 if (log.isTraceEnabled()) {
319 log.trace("Retrieving AuthorizationInfo for principals [" + principals + "]");
320 }
321
322 Cache<Object, AuthorizationInfo> cache = getAvailableAuthorizationCache();
323 if (cache != null) {
324 if (log.isTraceEnabled()) {
325 log.trace("Attempting to retrieve the AuthorizationInfo from cache.");
326 }
327 Object key = getAuthorizationCacheKey(principals);
328 info = cache.get(key);
329 if (log.isTraceEnabled()) {
330 if (info == null) {
331 log.trace("No AuthorizationInfo found in cache for principals [" + principals + "]");
332 } else {
333 log.trace("AuthorizationInfo found in cache for principals [" + principals + "]");
334 }
335 }
336 }
337
338
339 if (info == null) {
340
341 info = doGetAuthorizationInfo(principals);
342
343 if (info != null && cache != null) {
344 if (log.isTraceEnabled()) {
345 log.trace("Caching authorization info for principals: [" + principals + "].");
346 }
347 Object key = getAuthorizationCacheKey(principals);
348 cache.put(key, info);
349 }
350 }
351
352 return info;
353 }
354
355 protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
356 return principals;
357 }
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377 protected void clearCachedAuthorizationInfo(PrincipalCollection principals) {
378 if (principals == null) {
379 return;
380 }
381
382 Cache<Object, AuthorizationInfo> cache = getAvailableAuthorizationCache();
383
384 if (cache != null) {
385 Object key = getAuthorizationCacheKey(principals);
386 cache.remove(key);
387 }
388 }
389
390
391
392
393
394
395
396
397
398
399 protected abstract AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals);
400
401
402 protected Collection<Permission> getPermissions(AuthorizationInfo info) {
403 Set<Permission> permissions = new HashSet<Permission>();
404
405 if (info != null) {
406 Collection<Permission> perms = info.getObjectPermissions();
407 if (!CollectionUtils.isEmpty(perms)) {
408 permissions.addAll(perms);
409 }
410 perms = resolvePermissions(info.getStringPermissions());
411 if (!CollectionUtils.isEmpty(perms)) {
412 permissions.addAll(perms);
413 }
414
415 perms = resolveRolePermissions(info.getRoles());
416 if (!CollectionUtils.isEmpty(perms)) {
417 permissions.addAll(perms);
418 }
419 }
420
421 if (permissions.isEmpty()) {
422 return Collections.emptySet();
423 } else {
424 return Collections.unmodifiableSet(permissions);
425 }
426 }
427
428 private Collection<Permission> resolvePermissions(Collection<String> stringPerms) {
429 Collection<Permission> perms = Collections.emptySet();
430 PermissionResolver resolver = getPermissionResolver();
431 if (resolver != null && !CollectionUtils.isEmpty(stringPerms)) {
432 perms = new LinkedHashSet<Permission>(stringPerms.size());
433 for (String strPermission : stringPerms) {
434 Permission permission = resolver.resolvePermission(strPermission);
435 perms.add(permission);
436 }
437 }
438 return perms;
439 }
440
441 private Collection<Permission> resolveRolePermissions(Collection<String> roleNames) {
442 Collection<Permission> perms = Collections.emptySet();
443 RolePermissionResolver resolver = getRolePermissionResolver();
444 if (resolver != null && !CollectionUtils.isEmpty(roleNames)) {
445 perms = new LinkedHashSet<Permission>(roleNames.size());
446 for (String roleName : roleNames) {
447 Collection<Permission> resolved = resolver.resolvePermissionsInRole(roleName);
448 if (!CollectionUtils.isEmpty(resolved)) {
449 perms.addAll(resolved);
450 }
451 }
452 }
453 return perms;
454 }
455
456 public boolean isPermitted(PrincipalCollection principals, String permission) {
457 Permission p = getPermissionResolver().resolvePermission(permission);
458 return isPermitted(principals, p);
459 }
460
461 public boolean isPermitted(PrincipalCollection principals, Permission permission) {
462 AuthorizationInfo info = getAuthorizationInfo(principals);
463 return isPermitted(permission, info);
464 }
465
466
467 protected boolean isPermitted(Permission permission, AuthorizationInfo info) {
468 Collection<Permission> perms = getPermissions(info);
469 if (perms != null && !perms.isEmpty()) {
470 for (Permission perm : perms) {
471 if (perm.implies(permission)) {
472 return true;
473 }
474 }
475 }
476 return false;
477 }
478
479 public boolean[] isPermitted(PrincipalCollection subjectIdentifier, String... permissions) {
480 List<Permission> perms = new ArrayList<Permission>(permissions.length);
481 for (String permString : permissions) {
482 perms.add(getPermissionResolver().resolvePermission(permString));
483 }
484 return isPermitted(subjectIdentifier, perms);
485 }
486
487 public boolean[] isPermitted(PrincipalCollection principals, List<Permission> permissions) {
488 AuthorizationInfo info = getAuthorizationInfo(principals);
489 return isPermitted(permissions, info);
490 }
491
492 protected boolean[] isPermitted(List<Permission> permissions, AuthorizationInfo info) {
493 boolean[] result;
494 if (permissions != null && !permissions.isEmpty()) {
495 int size = permissions.size();
496 result = new boolean[size];
497 int i = 0;
498 for (Permission p : permissions) {
499 result[i++] = isPermitted(p, info);
500 }
501 } else {
502 result = new boolean[0];
503 }
504 return result;
505 }
506
507 public boolean isPermittedAll(PrincipalCollection subjectIdentifier, String... permissions) {
508 if (permissions != null && permissions.length > 0) {
509 Collection<Permission> perms = new ArrayList<Permission>(permissions.length);
510 for (String permString : permissions) {
511 perms.add(getPermissionResolver().resolvePermission(permString));
512 }
513 return isPermittedAll(subjectIdentifier, perms);
514 }
515 return false;
516 }
517
518 public boolean isPermittedAll(PrincipalCollection principal, Collection<Permission> permissions) {
519 AuthorizationInfo info = getAuthorizationInfo(principal);
520 return info != null && isPermittedAll(permissions, info);
521 }
522
523 protected boolean isPermittedAll(Collection<Permission> permissions, AuthorizationInfo info) {
524 if (permissions != null && !permissions.isEmpty()) {
525 for (Permission p : permissions) {
526 if (!isPermitted(p, info)) {
527 return false;
528 }
529 }
530 }
531 return true;
532 }
533
534 public void checkPermission(PrincipalCollection subjectIdentifier, String permission) throws AuthorizationException {
535 Permission p = getPermissionResolver().resolvePermission(permission);
536 checkPermission(subjectIdentifier, p);
537 }
538
539 public void checkPermission(PrincipalCollection principal, Permission permission) throws AuthorizationException {
540 AuthorizationInfo info = getAuthorizationInfo(principal);
541 checkPermission(permission, info);
542 }
543
544 protected void checkPermission(Permission permission, AuthorizationInfo info) {
545 if (!isPermitted(permission, info)) {
546 String msg = "User is not permitted [" + permission + "]";
547 throw new UnauthorizedException(msg);
548 }
549 }
550
551 public void checkPermissions(PrincipalCollection subjectIdentifier, String... permissions) throws AuthorizationException {
552 if (permissions != null) {
553 for (String permString : permissions) {
554 checkPermission(subjectIdentifier, permString);
555 }
556 }
557 }
558
559 public void checkPermissions(PrincipalCollection principal, Collection<Permission> permissions) throws AuthorizationException {
560 AuthorizationInfo info = getAuthorizationInfo(principal);
561 checkPermissions(permissions, info);
562 }
563
564 protected void checkPermissions(Collection<Permission> permissions, AuthorizationInfo info) {
565 if (permissions != null && !permissions.isEmpty()) {
566 for (Permission p : permissions) {
567 checkPermission(p, info);
568 }
569 }
570 }
571
572 public boolean hasRole(PrincipalCollection principal, String roleIdentifier) {
573 AuthorizationInfo info = getAuthorizationInfo(principal);
574 return hasRole(roleIdentifier, info);
575 }
576
577 protected boolean hasRole(String roleIdentifier, AuthorizationInfo info) {
578 return info != null && info.getRoles() != null && info.getRoles().contains(roleIdentifier);
579 }
580
581 public boolean[] hasRoles(PrincipalCollection principal, List<String> roleIdentifiers) {
582 AuthorizationInfo info = getAuthorizationInfo(principal);
583 boolean[] result = new boolean[roleIdentifiers != null ? roleIdentifiers.size() : 0];
584 if (info != null) {
585 result = hasRoles(roleIdentifiers, info);
586 }
587 return result;
588 }
589
590 protected boolean[] hasRoles(List<String> roleIdentifiers, AuthorizationInfo info) {
591 boolean[] result;
592 if (roleIdentifiers != null && !roleIdentifiers.isEmpty()) {
593 int size = roleIdentifiers.size();
594 result = new boolean[size];
595 int i = 0;
596 for (String roleName : roleIdentifiers) {
597 result[i++] = hasRole(roleName, info);
598 }
599 } else {
600 result = new boolean[0];
601 }
602 return result;
603 }
604
605 public boolean hasAllRoles(PrincipalCollection principal, Collection<String> roleIdentifiers) {
606 AuthorizationInfo info = getAuthorizationInfo(principal);
607 return info != null && hasAllRoles(roleIdentifiers, info);
608 }
609
610 private boolean hasAllRoles(Collection<String> roleIdentifiers, AuthorizationInfo info) {
611 if (roleIdentifiers != null && !roleIdentifiers.isEmpty()) {
612 for (String roleName : roleIdentifiers) {
613 if (!hasRole(roleName, info)) {
614 return false;
615 }
616 }
617 }
618 return true;
619 }
620
621 public void checkRole(PrincipalCollection principal, String role) throws AuthorizationException {
622 AuthorizationInfo info = getAuthorizationInfo(principal);
623 checkRole(role, info);
624 }
625
626 protected void checkRole(String role, AuthorizationInfo info) {
627 if (!hasRole(role, info)) {
628 String msg = "User does not have role [" + role + "]";
629 throw new UnauthorizedException(msg);
630 }
631 }
632
633 public void checkRoles(PrincipalCollection principal, Collection<String> roles) throws AuthorizationException {
634 AuthorizationInfo info = getAuthorizationInfo(principal);
635 checkRoles(roles, info);
636 }
637
638 public void checkRoles(PrincipalCollection principal, String... roles) throws AuthorizationException {
639 checkRoles(principal, Arrays.asList(roles));
640 }
641
642 protected void checkRoles(Collection<String> roles, AuthorizationInfo info) {
643 if (roles != null && !roles.isEmpty()) {
644 for (String roleName : roles) {
645 checkRole(roleName, info);
646 }
647 }
648 }
649
650
651
652
653
654
655
656
657
658
659
660 @Override
661 protected void doClearCache(PrincipalCollection principals) {
662 super.doClearCache(principals);
663 clearCachedAuthorizationInfo(principals);
664 }
665 }