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