shiro
CachingRealm
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.shiro.realm; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; /** * A <tt>Realm</tt> is a security component that can access application-specific security entities * such as users, roles, and permissions to determine authentication and authorization operations. * * <p><tt>Realm</tt>s usually have a 1-to-1 correspondence with a datasource such as a relational database, * file system, or other similar resource. As such, implementations of this interface use datasource-specific APIs to * determine authorization data (roles, permissions, etc), such as JDBC, File IO, Hibernate or JPA, or any other * Data Access API. They are essentially security-specific * <a href="http://en.wikipedia.org/wiki/Data_Access_Object" target="_blank">DAO</a>s. * * <p>Because most of these datasources usually contain Subject (a.k.a. User) information such as usernames and * passwords, a Realm can act as a pluggable authentication module in a * <a href="http://en.wikipedia.org/wiki/Pluggable_Authentication_Modules">PAM</a> configuration. This allows a Realm to * perform <i>both</i> authentication and authorization duties for a single datasource, which caters to the large * majority of applications. If for some reason you don't want your Realm implementation to perform authentication * duties, you should override the {@link #supports(org.apache.shiro.authc.AuthenticationToken)} method to always * return <tt>false</tt>. * * <p>Because every application is different, security data such as users and roles can be * represented in any number of ways. Shiro tries to maintain a non-intrusive development philosophy whenever * possible - it does not require you to implement or extend any <tt>User</tt>, <tt>Group</tt> or <tt>Role</tt> * interfaces or classes. * * <p>Instead, Shiro allows applications to implement this interface to access environment-specific datasources * and data model objects. The implementation can then be plugged in to the application's Shiro configuration. * This modular technique abstracts away any environment/modeling details and allows Shiro to be deployed in * practically any application environment. * * <p>Most users will not implement the <tt>Realm</tt> interface directly, but will extend one of the subclasses, * {@link org.apache.shiro.realm.AuthenticatingRealm AuthenticatingRealm} or {@link org.apache.shiro.realm.AuthorizingRealm}, greatly reducing the effort requird * to implement a <tt>Realm</tt> from scratch.</p> * * @see org.apache.shiro.realm.CachingRealm CachingRealm * @see org.apache.shiro.realm.AuthenticatingRealm AuthenticatingRealm * @see org.apache.shiro.realm.AuthorizingRealm AuthorizingRealm * @see org.apache.shiro.authc.pam.ModularRealmAuthenticator ModularRealmAuthenticator * @since 0.1 */ public interface Realm { /** * Returns the (application-unique) name assigned to this <code>Realm</code>. All realms configured for a single * application must have a unique name. * * @return the (application-unique) name assigned to this <code>Realm</code>. */ String getName(); /** * Returns <tt>true</tt> if this realm wishes to authenticate the Subject represented by the given * {@link org.apache.shiro.authc.AuthenticationToken AuthenticationToken} instance, <tt>false</tt> otherwise. * * <p>If this method returns <tt>false</tt>, it will not be called to authenticate the Subject represented by * the token - more specifically, a <tt>false</tt> return value means this Realm instance's * {@link #getAuthenticationInfo} method will not be invoked for that token. * * @param token the AuthenticationToken submitted for the authentication attempt * @return <tt>true</tt> if this realm can/will authenticate Subjects represented by specified token, * <tt>false</tt> otherwise. */ boolean supports(AuthenticationToken token); /** * Returns an account's authentication-specific information for the specified <tt>token</tt>, * or <tt>null</tt> if no account could be found based on the <tt>token</tt>. * * <p>This method effectively represents a login attempt for the corresponding user with the underlying EIS datasource. * Most implementations merely just need to lookup and return the account data only (as the method name implies) * and let Shiro do the rest, but implementations may of course perform eis specific login operations if so * desired. * * @param token the application-specific representation of an account principal and credentials. * @return the authentication information for the account associated with the specified <tt>token</tt>, * or <tt>null</tt> if no account could be found. * @throws org.apache.shiro.authc.AuthenticationException * if there is an error obtaining or constructing an AuthenticationInfo object based on the * specified <tt>token</tt> or implementation-specific login behavior fails. */ AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException; }
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.apache.shiro.util; public interface Nameable { void setName(String var1); }
1 // 2 // Source code recreated from a .class file by IntelliJ IDEA 3 // (powered by Fernflower decompiler) 4 // 5 6 package org.apache.shiro.cache; 7 8 public interface CacheManagerAware { 9 void setCacheManager(CacheManager var1); 10 }
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.authc; 20 21 import org.apache.shiro.subject.PrincipalCollection; 22 23 /** 24 * An SPI interface allowing cleanup logic to be executed during logout of a previously authenticated Subject/user. 25 * 26 * <p>As it is an SPI interface, it is really intended for SPI implementors such as those implementing Realms. 27 * 28 * <p>All of Shiro's concrete Realm implementations implement this interface as a convenience for those wishing 29 * to subclass them. 30 * 31 * @since 0.9 32 */ 33 public interface LogoutAware { 34 35 /** 36 * Callback triggered when a <code>Subject</code> logs out of the system. 37 * 38 * @param principals the identifying principals of the Subject logging out. 39 */ 40 public void onLogout(PrincipalCollection principals); 41 }
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.realm; 20 21 import org.apache.shiro.authc.AuthenticationException; 22 import org.apache.shiro.authc.AuthenticationInfo; 23 import org.apache.shiro.authc.AuthenticationToken; 24 import org.apache.shiro.authc.IncorrectCredentialsException; 25 import org.apache.shiro.authc.UsernamePasswordToken; 26 import org.apache.shiro.authc.credential.AllowAllCredentialsMatcher; 27 import org.apache.shiro.authc.credential.CredentialsMatcher; 28 import org.apache.shiro.authc.credential.SimpleCredentialsMatcher; 29 import org.apache.shiro.cache.Cache; 30 import org.apache.shiro.cache.CacheManager; 31 import org.apache.shiro.subject.PrincipalCollection; 32 import org.apache.shiro.util.Initializable; 33 import org.slf4j.Logger; 34 import org.slf4j.LoggerFactory; 35 36 import java.util.concurrent.atomic.AtomicInteger; 37 38 39 /** 40 * A top-level abstract implementation of the <tt>Realm</tt> interface that only implements authentication support 41 * (log-in) operations and leaves authorization (access control) behavior to subclasses. 42 * <h2>Authentication Caching</h2> 43 * For applications that perform frequent repeated authentication of the same accounts (e.g. as is often done in 44 * REST or Soap applications that authenticate on every request), it might be prudent to enable authentication 45 * caching to alleviate constant load on any back-end data sources. 46 * <p/> 47 * This feature is disabled by default to retain backwards-compatibility with Shiro 1.1 and earlier. It may be 48 * enabled by setting {@link #setAuthenticationCachingEnabled(boolean) authenticationCachingEnabled} = {@code true} 49 * (and configuring Shiro with a {@link CacheManager} of course), but <b>NOTE:</b> 50 * <p/> 51 * <b>ONLY enable authentication caching if either of the following is true for your realm implementation:</b> 52 * <ul> 53 * <li>The {@link #doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken) doGetAuthenticationInfo} 54 * implementation returns {@code AuthenticationInfo} instances where the 55 * {@link org.apache.shiro.authc.AuthenticationInfo#getCredentials() credentials} are securely obfuscated and NOT 56 * plaintext (raw) credentials. For example, 57 * if your realm references accounts with passwords, that the {@code AuthenticationInfo}'s 58 * {@link org.apache.shiro.authc.AuthenticationInfo#getCredentials() credentials} are safely hashed and salted or otherwise 59 * fully encrypted.<br/><br/></li> 60 * <li>The {@link #doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken) doGetAuthenticationInfo} 61 * implementation returns {@code AuthenticationInfo} instances where the 62 * {@link org.apache.shiro.authc.AuthenticationInfo#getCredentials() credentials} are plaintext (raw) <b>AND</b> the 63 * cache region storing the {@code AuthenticationInfo} instances WILL NOT overflow to disk and WILL NOT transmit cache 64 * entries over an unprotected (non TLS/SSL) network (as might be the case with a networked/distributed enterprise cache). 65 * This should be the case even in private/trusted/corporate networks.</li> 66 * </ul> 67 * <p/> 68 * These points are very important because if authentication caching is enabled, this abstract class implementation 69 * will place AuthenticationInfo instances returned from the subclass implementations directly into the cache, for 70 * example: 71 * <pre> 72 * cache.put(cacheKey, subclassAuthenticationInfoInstance); 73 * </pre> 74 * <p/> 75 * Enabling authentication caching is ONLY safe to do if the above two scenarios apply. It is NOT safe to enable under 76 * any other scenario. 77 * <p/> 78 * When possible, always represent and store credentials in a safe form (hash+salt or encrypted) to eliminate plaintext 79 * visibility. 80 * <h3>Authentication Cache Invalidation on Logout</h3> 81 * If authentication caching is enabled, this implementation will attempt to evict (remove) cached authentication data 82 * for an account during logout. This can only occur if the 83 * {@link #getAuthenticationCacheKey(org.apache.shiro.authc.AuthenticationToken)} and 84 * {@link #getAuthenticationCacheKey(org.apache.shiro.subject.PrincipalCollection)} methods return the exact same value. 85 * <p/> 86 * The default implementations of these methods expect that the 87 * {@link org.apache.shiro.authc.AuthenticationToken#getPrincipal()} (what the user submits during login) and 88 * {@link #getAvailablePrincipal(org.apache.shiro.subject.PrincipalCollection) getAvailablePrincipal} (what is returned 89 * by the realm after account lookup) return 90 * the same exact value. For example, the user submitted username is also the primary account identifier. 91 * <p/> 92 * However, if your application uses, say, a username for end-user login, but returns a primary key ID as the 93 * primary principal after authentication, then you will need to override either 94 * {@link #getAuthenticationCacheKey(org.apache.shiro.authc.AuthenticationToken) getAuthenticationCacheKey(token)} or 95 * {@link #getAuthenticationCacheKey(org.apache.shiro.subject.PrincipalCollection) getAuthenticationCacheKey(principals)} 96 * (or both) to ensure that the same cache key can be used for either object. 97 * <p/> 98 * This guarantees that the same cache key used to cache the data during authentication (derived from the 99 * {@code AuthenticationToken}) will be used to remove the cached data during logout (derived from the 100 * {@code PrincipalCollection}). 101 * <h4>Unmatching Cache Key Values</h4> 102 * If the return values from {@link #getAuthenticationCacheKey(org.apache.shiro.authc.AuthenticationToken)} and 103 * {@link #getAuthenticationCacheKey(org.apache.shiro.subject.PrincipalCollection)} are not identical, cached 104 * authentication data removal is at the mercy of your cache provider settings. For example, often cache 105 * implementations will evict cache entries based on a timeToIdle or timeToLive (TTL) value. 106 * <p/> 107 * If this lazy eviction capability of the cache product is not sufficient and you want discrete behavior 108 * (highly recommended for authentication data), ensure that the return values from those two methods are identical in 109 * the subclass implementation. 110 * 111 * @since 0.2 112 */ 113 public abstract class AuthenticatingRealm extends CachingRealm implements Initializable { 114 115 //TODO - complete JavaDoc 116 117 private static final Logger log = LoggerFactory.getLogger(AuthenticatingRealm.class); 118 119 private static final AtomicInteger INSTANCE_COUNT = new AtomicInteger(); 120 121 /** 122 * The default suffix appended to the realm name used for caching authentication data. 123 * 124 * @since 1.2 125 */ 126 private static final String DEFAULT_AUTHORIZATION_CACHE_SUFFIX = ".authenticationCache"; 127 128 /** 129 * Credentials matcher used to determine if the provided credentials match the credentials stored in the data store. 130 */ 131 private CredentialsMatcher credentialsMatcher; 132 133 134 private Cache<Object, AuthenticationInfo> authenticationCache; 135 136 private boolean authenticationCachingEnabled; 137 private String authenticationCacheName; 138 139 /** 140 * The class that this realm supports for authentication tokens. This is used by the 141 * default implementation of the {@link Realm#supports(org.apache.shiro.authc.AuthenticationToken)} method to 142 * determine whether or not the given authentication token is supported by this realm. 143 */ 144 private Class<? extends AuthenticationToken> authenticationTokenClass; 145 146 /*------------------------------------------- 147 | C O N S T R U C T O R S | 148 ============================================*/ 149 public AuthenticatingRealm() { 150 this(null, new SimpleCredentialsMatcher()); 151 } 152 153 public AuthenticatingRealm(CacheManager cacheManager) { 154 this(cacheManager, new SimpleCredentialsMatcher()); 155 } 156 157 public AuthenticatingRealm(CredentialsMatcher matcher) { 158 this(null, matcher); 159 } 160 161 public AuthenticatingRealm(CacheManager cacheManager, CredentialsMatcher matcher) { 162 authenticationTokenClass = UsernamePasswordToken.class; 163 164 //retain backwards compatibility for Shiro 1.1 and earlier. Setting to true by default will probably cause 165 //unexpected results for existing applications: 166 this.authenticationCachingEnabled = false; 167 168 int instanceNumber = INSTANCE_COUNT.getAndIncrement(); 169 this.authenticationCacheName = getClass().getName() + DEFAULT_AUTHORIZATION_CACHE_SUFFIX; 170 if (instanceNumber > 0) { 171 this.authenticationCacheName = this.authenticationCacheName + "." + instanceNumber; 172 } 173 174 if (cacheManager != null) { 175 setCacheManager(cacheManager); 176 } 177 if (matcher != null) { 178 setCredentialsMatcher(matcher); 179 } 180 } 181 182 /*-------------------------------------------- 183 | A C C E S S O R S / M O D I F I E R S | 184 ============================================*/ 185 186 /** 187 * Returns the <code>CredentialsMatcher</code> used during an authentication attempt to verify submitted 188 * credentials with those stored in the system. 189 * <p/> 190 * <p>Unless overridden by the {@link #setCredentialsMatcher setCredentialsMatcher} method, the default 191 * value is a {@link org.apache.shiro.authc.credential.SimpleCredentialsMatcher SimpleCredentialsMatcher} instance. 192 * 193 * @return the <code>CredentialsMatcher</code> used during an authentication attempt to verify submitted 194 * credentials with those stored in the system. 195 */ 196 public CredentialsMatcher getCredentialsMatcher() { 197 return credentialsMatcher; 198 } 199 200 /** 201 * Sets the CrendialsMatcher used during an authentication attempt to verify submitted credentials with those 202 * stored in the system. The implementation of this matcher can be switched via configuration to 203 * support any number of schemes, including plain text comparisons, hashing comparisons, and others. 204 * <p/> 205 * <p>Unless overridden by this method, the default value is a 206 * {@link org.apache.shiro.authc.credential.SimpleCredentialsMatcher} instance. 207 * 208 * @param credentialsMatcher the matcher to use. 209 */ 210 public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) { 211 this.credentialsMatcher = credentialsMatcher; 212 } 213 214 /** 215 * Returns the authenticationToken class supported by this realm. 216 * <p/> 217 * <p>The default value is <tt>{@link org.apache.shiro.authc.UsernamePasswordToken UsernamePasswordToken.class}</tt>, since 218 * about 90% of realms use username/password authentication, regardless of their protocol (e.g. over jdbc, ldap, 219 * kerberos, http, etc). 220 * <p/> 221 * <p>If subclasses haven't already overridden the {@link Realm#supports Realm.supports(AuthenticationToken)} method, 222 * they must {@link #setAuthenticationTokenClass(Class) set a new class} if they won't support 223 * <tt>UsernamePasswordToken</tt> authentication token submissions. 224 * 225 * @return the authenticationToken class supported by this realm. 226 * @see #setAuthenticationTokenClass 227 */ 228 public Class getAuthenticationTokenClass() { 229 return authenticationTokenClass; 230 } 231 232 /** 233 * Sets the authenticationToken class supported by this realm. 234 * <p/> 235 * <p>Unless overridden by this method, the default value is 236 * {@link org.apache.shiro.authc.UsernamePasswordToken UsernamePasswordToken.class} to support the majority of applications. 237 * 238 * @param authenticationTokenClass the class of authentication token instances supported by this realm. 239 * @see #getAuthenticationTokenClass getAuthenticationTokenClass() for more explanation. 240 */ 241 public void setAuthenticationTokenClass(Class<? extends AuthenticationToken> authenticationTokenClass) { 242 this.authenticationTokenClass = authenticationTokenClass; 243 } 244 245 /** 246 * Sets an explicit {@link Cache} instance to use for authentication caching. If not set and authentication 247 * caching is {@link #isAuthenticationCachingEnabled() enabled}, any available 248 * {@link #getCacheManager() cacheManager} will be used to acquire the cache instance if available. 249 * <p/> 250 * <b>WARNING:</b> Only set this property if safe caching conditions apply, as documented at the top 251 * of this page in the class-level JavaDoc. 252 * 253 * @param authenticationCache an explicit {@link Cache} instance to use for authentication caching or 254 * {@code null} if the cache should possibly be obtained another way. 255 * @see #isAuthenticationCachingEnabled() 256 * @since 1.2 257 */ 258 public void setAuthenticationCache(Cache<Object, AuthenticationInfo> authenticationCache) { 259 this.authenticationCache = authenticationCache; 260 } 261 262 /** 263 * Returns a {@link Cache} instance to use for authentication caching, or {@code null} if no cache has been 264 * set. 265 * 266 * @return a {@link Cache} instance to use for authentication caching, or {@code null} if no cache has been 267 * set. 268 * @see #setAuthenticationCache(org.apache.shiro.cache.Cache) 269 * @see #isAuthenticationCachingEnabled() 270 * @since 1.2 271 */ 272 public Cache<Object, AuthenticationInfo> getAuthenticationCache() { 273 return this.authenticationCache; 274 } 275 276 /** 277 * Returns the name of a {@link Cache} to lookup from any available {@link #getCacheManager() cacheManager} if 278 * a cache is not explicitly configured via {@link #setAuthenticationCache(org.apache.shiro.cache.Cache)}. 279 * <p/> 280 * This name will only be used to look up a cache if authentication caching is 281 * {@link #isAuthenticationCachingEnabled() enabled}. 282 * <p/> 283 * <b>WARNING:</b> Only set this property if safe caching conditions apply, as documented at the top 284 * of this page in the class-level JavaDoc. 285 * 286 * @return the name of a {@link Cache} to lookup from any available {@link #getCacheManager() cacheManager} if 287 * a cache is not explicitly configured via {@link #setAuthenticationCache(org.apache.shiro.cache.Cache)}. 288 * @see #isAuthenticationCachingEnabled() 289 * @since 1.2 290 */ 291 public String getAuthenticationCacheName() { 292 return this.authenticationCacheName; 293 } 294 295 /** 296 * Sets the name of a {@link Cache} to lookup from any available {@link #getCacheManager() cacheManager} if 297 * a cache is not explicitly configured via {@link #setAuthenticationCache(org.apache.shiro.cache.Cache)}. 298 * <p/> 299 * This name will only be used to look up a cache if authentication caching is 300 * {@link #isAuthenticationCachingEnabled() enabled}. 301 * 302 * @param authenticationCacheName the name of a {@link Cache} to lookup from any available 303 * {@link #getCacheManager() cacheManager} if a cache is not explicitly configured 304 * via {@link #setAuthenticationCache(org.apache.shiro.cache.Cache)}. 305 * @see #isAuthenticationCachingEnabled() 306 * @since 1.2 307 */ 308 public void setAuthenticationCacheName(String authenticationCacheName) { 309 this.authenticationCacheName = authenticationCacheName; 310 } 311 312 /** 313 * Returns {@code true} if authentication caching should be utilized if a {@link CacheManager} has been 314 * {@link #setCacheManager(org.apache.shiro.cache.CacheManager) configured}, {@code false} otherwise. 315 * <p/> 316 * The default value is {@code true}. 317 * 318 * @return {@code true} if authentication caching should be utilized, {@code false} otherwise. 319 */ 320 public boolean isAuthenticationCachingEnabled() { 321 return this.authenticationCachingEnabled && isCachingEnabled(); 322 } 323 324 /** 325 * Sets whether or not authentication caching should be utilized if a {@link CacheManager} has been 326 * {@link #setCacheManager(org.apache.shiro.cache.CacheManager) configured}, {@code false} otherwise. 327 * <p/> 328 * The default value is {@code false} to retain backwards compatibility with Shiro 1.1 and earlier. 329 * <p/> 330 * <b>WARNING:</b> Only set this property to {@code true} if safe caching conditions apply, as documented at the top 331 * of this page in the class-level JavaDoc. 332 * 333 * @param authenticationCachingEnabled the value to set 334 */ 335 @SuppressWarnings({"UnusedDeclaration"}) 336 public void setAuthenticationCachingEnabled(boolean authenticationCachingEnabled) { 337 this.authenticationCachingEnabled = authenticationCachingEnabled; 338 if (authenticationCachingEnabled) { 339 setCachingEnabled(true); 340 } 341 } 342 343 public void setName(String name) { 344 super.setName(name); 345 String authcCacheName = this.authenticationCacheName; 346 if (authcCacheName != null && authcCacheName.startsWith(getClass().getName())) { 347 //get rid of the default heuristically-created cache name. Create a more meaningful one 348 //based on the application-unique Realm name: 349 this.authenticationCacheName = name + DEFAULT_AUTHORIZATION_CACHE_SUFFIX; 350 } 351 } 352 353 354 /*-------------------------------------------- 355 | M E T H O D S | 356 ============================================*/ 357 358 /** 359 * Convenience implementation that returns 360 * <tt>getAuthenticationTokenClass().isAssignableFrom( token.getClass() );</tt>. Can be overridden 361 * by subclasses for more complex token checking. 362 * <p>Most configurations will only need to set a different class via 363 * {@link #setAuthenticationTokenClass}, as opposed to overriding this method. 364 * 365 * @param token the token being submitted for authentication. 366 * @return true if this authentication realm can process the submitted token instance of the class, false otherwise. 367 */ 368 public boolean supports(AuthenticationToken token) { 369 return token != null && getAuthenticationTokenClass().isAssignableFrom(token.getClass()); 370 } 371 372 /** 373 * Initializes this realm and potentially enables an authentication cache, depending on configuration. Based on 374 * the availability of an authentication cache, this class functions as follows: 375 * <ol> 376 * <li>If the {@link #setAuthenticationCache cache} property has been set, it will be 377 * used to cache the AuthenticationInfo objects returned from {@link #getAuthenticationInfo} 378 * method invocations. 379 * All future calls to {@link #getAuthenticationInfo} will attempt to use this cache first 380 * to alleviate any potentially unnecessary calls to an underlying data store.</li> 381 * <li>If the {@link #setAuthenticationCache cache} property has <b>not</b> been set, 382 * the {@link #setCacheManager cacheManager} property will be checked. 383 * If a {@code cacheManager} has been set, it will be used to eagerly acquire an authentication 384 * {@code cache}, and this cache which will be used as specified in #1.</li> 385 * <li>If neither the {@link #setAuthenticationCache (org.apache.shiro.cache.Cache) authenticationCache} 386 * or {@link #setCacheManager(org.apache.shiro.cache.CacheManager) cacheManager} 387 * properties are set, caching will not be utilized and authentication look-ups will be delegated to 388 * subclass implementations for each authentication attempt.</li> 389 * </ol> 390 * <p/> 391 * This method finishes by calling {@link #onInit()} is to allow subclasses to perform any init behavior desired. 392 * 393 * @since 1.2 394 */ 395 public final void init() { 396 //trigger obtaining the authorization cache if possible 397 getAvailableAuthenticationCache(); 398 onInit(); 399 } 400 401 /** 402 * Template method for subclasses to implement any initialization logic. Called from 403 * {@link #init()}. 404 * 405 * @since 1.2 406 */ 407 protected void onInit() { 408 } 409 410 /** 411 * This implementation attempts to acquire an authentication cache if one is not already configured. 412 * 413 * @since 1.2 414 */ 415 protected void afterCacheManagerSet() { 416 //trigger obtaining the authorization cache if possible 417 getAvailableAuthenticationCache(); 418 } 419 420 /** 421 * Returns any available {@link Cache} instance to use for authentication caching. This functions as follows: 422 * <ol> 423 * <li>If an {@link #setAuthenticationCache(org.apache.shiro.cache.Cache) authenticationCache} has been explicitly 424 * configured (it is not null), it is returned.</li> 425 * <li>If there is no {@link #getAuthenticationCache() authenticationCache} configured: 426 * <ol> 427 * <li>If authentication caching is {@link #isAuthenticationCachingEnabled() enabled}, any available 428 * {@link #getCacheManager() cacheManager} will be consulted to obtain an available authentication cache. 429 * </li> 430 * <li>If authentication caching is disabled, this implementation does nothing.</li> 431 * </ol> 432 * </li> 433 * </ol> 434 * 435 * @return any available {@link Cache} instance to use for authentication caching. 436 */ 437 private Cache<Object, AuthenticationInfo> getAvailableAuthenticationCache() { 438 Cache<Object, AuthenticationInfo> cache = getAuthenticationCache(); 439 boolean authcCachingEnabled = isAuthenticationCachingEnabled(); 440 if (cache == null && authcCachingEnabled) { 441 cache = getAuthenticationCacheLazy(); 442 } 443 return cache; 444 } 445 446 /** 447 * Checks to see if the authenticationCache class attribute is null, and if so, attempts to acquire one from 448 * any configured {@link #getCacheManager() cacheManager}. If one is acquired, it is set as the class attribute. 449 * The class attribute is then returned. 450 * 451 * @return an available cache instance to be used for authentication caching or {@code null} if one is not available. 452 * @since 1.2 453 */ 454 private Cache<Object, AuthenticationInfo> getAuthenticationCacheLazy() { 455 456 if (this.authenticationCache == null) { 457 458 log.trace("No authenticationCache instance set. Checking for a cacheManager..."); 459 460 CacheManager cacheManager = getCacheManager(); 461 462 if (cacheManager != null) { 463 String cacheName = getAuthenticationCacheName(); 464 log.debug("CacheManager [{}] configured. Building authentication cache '{}'", cacheManager, cacheName); 465 this.authenticationCache = cacheManager.getCache(cacheName); 466 } 467 } 468 469 return this.authenticationCache; 470 } 471 472 /** 473 * Returns any cached AuthenticationInfo corresponding to the specified token or {@code null} if there currently 474 * isn't any cached data. 475 * 476 * @param token the token submitted during the authentication attempt. 477 * @return any cached AuthenticationInfo corresponding to the specified token or {@code null} if there currently 478 * isn't any cached data. 479 * @since 1.2 480 */ 481 private AuthenticationInfo getCachedAuthenticationInfo(AuthenticationToken token) { 482 AuthenticationInfo info = null; 483 484 Cache<Object, AuthenticationInfo> cache = getAvailableAuthenticationCache(); 485 if (cache != null && token != null) { 486 log.trace("Attempting to retrieve the AuthenticationInfo from cache."); 487 Object key = getAuthenticationCacheKey(token); 488 info = cache.get(key); 489 if (info == null) { 490 log.trace("No AuthorizationInfo found in cache for key [{}]", key); 491 } else { 492 log.trace("Found cached AuthorizationInfo for key [{}]", key); 493 } 494 } 495 496 return info; 497 } 498 499 /** 500 * Caches the specified info if authentication caching 501 * {@link #isAuthenticationCachingEnabled(org.apache.shiro.authc.AuthenticationToken, org.apache.shiro.authc.AuthenticationInfo) isEnabled} 502 * for the specific token/info pair and a cache instance is available to be used. 503 * 504 * @param token the authentication token submitted which resulted in a successful authentication attempt. 505 * @param info the AuthenticationInfo to cache as a result of the successful authentication attempt. 506 * @since 1.2 507 */ 508 private void cacheAuthenticationInfoIfPossible(AuthenticationToken token, AuthenticationInfo info) { 509 if (!isAuthenticationCachingEnabled(token, info)) { 510 log.debug("AuthenticationInfo caching is disabled for info [{}]. Submitted token: [{}].", info, token); 511 //return quietly, caching is disabled for this token/info pair: 512 return; 513 } 514 515 Cache<Object, AuthenticationInfo> cache = getAvailableAuthenticationCache(); 516 if (cache != null) { 517 Object key = getAuthenticationCacheKey(token); 518 cache.put(key, info); 519 log.trace("Cached AuthenticationInfo for continued authentication. key=[{}], value=[{}].", key, info); 520 } 521 } 522 523 /** 524 * Returns {@code true} if authentication caching should be utilized based on the specified 525 * {@link AuthenticationToken} and/or {@link AuthenticationInfo}, {@code false} otherwise. 526 * <p/> 527 * The default implementation simply delegates to {@link #isAuthenticationCachingEnabled()}, the general-case 528 * authentication caching setting. Subclasses can override this to turn on or off caching at runtime 529 * based on the specific submitted runtime values. 530 * 531 * @param token the submitted authentication token 532 * @param info the {@code AuthenticationInfo} acquired from data source lookup via 533 * {@link #doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken)} 534 * @return {@code true} if authentication caching should be utilized based on the specified 535 * {@link AuthenticationToken} and/or {@link AuthenticationInfo}, {@code false} otherwise. 536 * @since 1.2 537 */ 538 protected boolean isAuthenticationCachingEnabled(AuthenticationToken token, AuthenticationInfo info) { 539 return isAuthenticationCachingEnabled(); 540 } 541 542 /** 543 * This implementation functions as follows: 544 * <ol> 545 * <li>It attempts to acquire any cached {@link AuthenticationInfo} corresponding to the specified 546 * {@link AuthenticationToken} argument. If a cached value is found, it will be used for credentials matching, 547 * alleviating the need to perform any lookups with a data source.</li> 548 * <li>If there is no cached {@link AuthenticationInfo} found, delegate to the 549 * {@link #doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken)} method to perform the actual 550 * lookup. If authentication caching is enabled and possible, any returned info object will be 551 * {@link #cacheAuthenticationInfoIfPossible(org.apache.shiro.authc.AuthenticationToken, org.apache.shiro.authc.AuthenticationInfo) cached} 552 * to be used in future authentication attempts.</li> 553 * <li>If an AuthenticationInfo instance is not found in the cache or by lookup, {@code null} is returned to 554 * indicate an account cannot be found.</li> 555 * <li>If an AuthenticationInfo instance is found (either cached or via lookup), ensure the submitted 556 * AuthenticationToken's credentials match the expected {@code AuthenticationInfo}'s credentials using the 557 * {@link #getCredentialsMatcher() credentialsMatcher}. This means that credentials are always verified 558 * for an authentication attempt.</li> 559 * </ol> 560 * 561 * @param token the submitted account principal and credentials. 562 * @return the AuthenticationInfo corresponding to the given {@code token}, or {@code null} if no 563 * AuthenticationInfo could be found. 564 * @throws AuthenticationException if authentication failed. 565 */ 566 public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 567 568 AuthenticationInfo info = getCachedAuthenticationInfo(token); 569 if (info == null) { 570 //otherwise not cached, perform the lookup: 571 info = doGetAuthenticationInfo(token); 572 log.debug("Looked up AuthenticationInfo [{}] from doGetAuthenticationInfo", info); 573 if (token != null && info != null) { 574 cacheAuthenticationInfoIfPossible(token, info); 575 } 576 } else { 577 log.debug("Using cached authentication info [{}] to perform credentials matching.", info); 578 } 579 580 if (info != null) { 581 assertCredentialsMatch(token, info); 582 } else { 583 log.debug("No AuthenticationInfo found for submitted AuthenticationToken [{}]. Returning null.", token); 584 } 585 586 return info; 587 } 588 589 /** 590 * Asserts that the submitted {@code AuthenticationToken}'s credentials match the stored account 591 * {@code AuthenticationInfo}'s credentials, and if not, throws an {@link AuthenticationException}. 592 * 593 * @param token the submitted authentication token 594 * @param info the AuthenticationInfo corresponding to the given {@code token} 595 * @throws AuthenticationException if the token's credentials do not match the stored account credentials. 596 */ 597 protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException { 598 CredentialsMatcher cm = getCredentialsMatcher(); 599 if (cm != null) { 600 if (!cm.doCredentialsMatch(token, info)) { 601 //not successful - throw an exception to indicate this: 602 String msg = "Submitted credentials for token [" + token + "] did not match the expected credentials."; 603 throw new IncorrectCredentialsException(msg); 604 } 605 } else { 606 throw new AuthenticationException("A CredentialsMatcher must be configured in order to verify " + 607 "credentials during authentication. If you do not wish for credentials to be examined, you " + 608 "can configure an " + AllowAllCredentialsMatcher.class.getName() + " instance."); 609 } 610 } 611 612 /** 613 * Returns the key under which {@link AuthenticationInfo} instances are cached if authentication caching is enabled. 614 * This implementation defaults to returning the token's 615 * {@link org.apache.shiro.authc.AuthenticationToken#getPrincipal() principal}, which is usually a username in 616 * most applications. 617 * <h3>Cache Invalidation on Logout</h3> 618 * <b>NOTE:</b> If you want to be able to invalidate an account's cached {@code AuthenticationInfo} on logout, you 619 * must ensure the {@link #getAuthenticationCacheKey(org.apache.shiro.subject.PrincipalCollection)} method returns 620 * the same value as this method. 621 * 622 * @param token the authentication token for which any successful authentication will be cached. 623 * @return the cache key to use to cache the associated {@link AuthenticationInfo} after a successful authentication. 624 * @since 1.2 625 */ 626 protected Object getAuthenticationCacheKey(AuthenticationToken token) { 627 return token != null ? token.getPrincipal() : null; 628 } 629 630 /** 631 * Returns the key under which {@link AuthenticationInfo} instances are cached if authentication caching is enabled. 632 * This implementation delegates to 633 * {@link #getAvailablePrincipal(org.apache.shiro.subject.PrincipalCollection)}, which returns the primary principal 634 * associated with this particular Realm. 635 * <h3>Cache Invalidation on Logout</h3> 636 * <b>NOTE:</b> If you want to be able to invalidate an account's cached {@code AuthenticationInfo} on logout, you 637 * must ensure that this method returns the same value as the 638 * {@link #getAuthenticationCacheKey(org.apache.shiro.authc.AuthenticationToken)} method! 639 * 640 * @param principals the principals of the account for which to set or remove cached {@code AuthenticationInfo}. 641 * @return the cache key to use when looking up cached {@link AuthenticationInfo} instances. 642 * @since 1.2 643 */ 644 protected Object getAuthenticationCacheKey(PrincipalCollection principals) { 645 return getAvailablePrincipal(principals); 646 } 647 648 /** 649 * This implementation clears out any cached authentication data by calling 650 * {@link #clearCachedAuthenticationInfo(org.apache.shiro.subject.PrincipalCollection)}. 651 * If overriding in a subclass, be sure to call {@code super.doClearCache} to ensure this behavior is maintained. 652 * 653 * @param principals principals the principals of the account for which to clear any cached data. 654 * @since 1.2 655 */ 656 @Override 657 protected void doClearCache(PrincipalCollection principals) { 658 super.doClearCache(principals); 659 clearCachedAuthenticationInfo(principals); 660 } 661 662 private static boolean isEmpty(PrincipalCollection pc) { 663 return pc == null || pc.isEmpty(); 664 } 665 666 /** 667 * Clears out the AuthenticationInfo cache entry for the specified account. 668 * <p/> 669 * This method is provided as a convenience to subclasses so they can invalidate a cache entry when they 670 * change an account's authentication data (e.g. reset password) during runtime. Because an account's 671 * AuthenticationInfo can be cached, there needs to be a way to invalidate the cache for only that account so that 672 * subsequent authentication operations don't used the (old) cached value if account data changes. 673 * <p/> 674 * After this method is called, the next authentication for that same account will result in a call to 675 * {@link #doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken) doGetAuthenticationInfo}, and the 676 * resulting return value will be cached before being returned so it can be reused for later authentications. 677 * <p/> 678 * If you wish to clear out all associated cached data (and not just authentication data), use the 679 * {@link #clearCache(org.apache.shiro.subject.PrincipalCollection)} method instead (which will in turn call this 680 * method by default). 681 * 682 * @param principals the principals of the account for which to clear the cached AuthorizationInfo. 683 * @see #clearCache(org.apache.shiro.subject.PrincipalCollection) 684 * @since 1.2 685 */ 686 protected void clearCachedAuthenticationInfo(PrincipalCollection principals) { 687 if (!isEmpty(principals)) { 688 Cache<Object, AuthenticationInfo> cache = getAvailableAuthenticationCache(); 689 //cache instance will be non-null if caching is enabled: 690 if (cache != null) { 691 Object key = getAuthenticationCacheKey(principals); 692 cache.remove(key); 693 } 694 } 695 } 696 697 /** 698 * Retrieves authentication data from an implementation-specific datasource (RDBMS, LDAP, etc) for the given 699 * authentication token. 700 * <p/> 701 * For most datasources, this means just 'pulling' authentication data for an associated subject/user and nothing 702 * more and letting Shiro do the rest. But in some systems, this method could actually perform EIS specific 703 * log-in logic in addition to just retrieving data - it is up to the Realm implementation. 704 * <p/> 705 * A {@code null} return value means that no account could be associated with the specified token. 706 * 707 * @param token the authentication token containing the user's principal and credentials. 708 * @return an {@link AuthenticationInfo} object containing account data resulting from the 709 * authentication ONLY if the lookup is successful (i.e. account exists and is valid, etc.) 710 * @throws AuthenticationException if there is an error acquiring data or performing 711 * realm-specific authentication logic for the specified <tt>token</tt> 712 */ 713 protected abstract AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException; 714 715 }
1 // 2 // Source code recreated from a .class file by IntelliJ IDEA 3 // (powered by Fernflower decompiler) 4 // 5 6 package org.apache.shiro.util; 7 8 import org.apache.shiro.ShiroException; 9 10 public interface Initializable { 11 void init() throws ShiroException; 12 }
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.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 * An {@code AuthorizingRealm} extends the {@code AuthenticatingRealm}'s capabilities by adding Authorization 38 * (access control) support. 39 * <p/> 40 * This implementation will perform all role and permission checks automatically (and subclasses do not have to 41 * write this logic) as long as the 42 * {@link #getAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection)} method returns an 43 * {@link AuthorizationInfo}. Please see that method's JavaDoc for an in-depth explanation. 44 * <p/> 45 * If you find that you do not want to utilize the {@link AuthorizationInfo AuthorizationInfo} construct, 46 * you are of course free to subclass the {@link AuthenticatingRealm AuthenticatingRealm} directly instead and 47 * implement the remaining Realm interface methods directly. You might do this if you want have better control 48 * over how the Role and Permission checks occur for your specific data source. However, using AuthorizationInfo 49 * (and its default implementation {@link org.apache.shiro.authz.SimpleAuthorizationInfo SimpleAuthorizationInfo}) is sufficient in the large 50 * majority of Realm cases. 51 * 52 * @see org.apache.shiro.authz.SimpleAuthorizationInfo 53 * @since 0.2 54 */ 55 public abstract class AuthorizingRealm extends AuthenticatingRealm 56 implements Authorizer, Initializable, PermissionResolverAware, RolePermissionResolverAware { 57 58 //TODO - complete JavaDoc 59 60 /*------------------------------------------- 61 | C O N S T A N T S | 62 ============================================*/ 63 private static final Logger log = LoggerFactory.getLogger(AuthorizingRealm.class); 64 65 /** 66 * The default suffix appended to the realm name for caching AuthorizationInfo instances. 67 */ 68 private static final String DEFAULT_AUTHORIZATION_CACHE_SUFFIX = ".authorizationCache"; 69 70 private static final AtomicInteger INSTANCE_COUNT = new AtomicInteger(); 71 72 /*------------------------------------------- 73 | I N S T A N C E V A R I A B L E S | 74 ============================================*/ 75 /** 76 * The cache used by this realm to store AuthorizationInfo instances associated with individual Subject principals. 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 | C O N S T R U C T O R S | 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 | A C C E S S O R S / M O D I F I E R S | 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 //get rid of the default class-name based cache name. Create a more meaningful one 126 //based on the application-unique Realm name: 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 * Returns {@code true} if authorization caching should be utilized if a {@link CacheManager} has been 150 * {@link #setCacheManager(org.apache.shiro.cache.CacheManager) configured}, {@code false} otherwise. 151 * <p/> 152 * The default value is {@code true}. 153 * 154 * @return {@code true} if authorization caching should be utilized, {@code false} otherwise. 155 */ 156 public boolean isAuthorizationCachingEnabled() { 157 return isCachingEnabled() && authorizationCachingEnabled; 158 } 159 160 /** 161 * Sets whether or not authorization caching should be utilized if a {@link CacheManager} has been 162 * {@link #setCacheManager(org.apache.shiro.cache.CacheManager) configured}, {@code false} otherwise. 163 * <p/> 164 * The default value is {@code true}. 165 * 166 * @param authenticationCachingEnabled the value to set 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 | M E T H O D S | 195 ============================================*/ 196 197 /** 198 * Initializes this realm and potentially enables a cache, depending on configuration. 199 * <p/> 200 * When this method is called, the following logic is executed: 201 * <ol> 202 * <li>If the {@link #setAuthorizationCache cache} property has been set, it will be 203 * used to cache the AuthorizationInfo objects returned from {@link #getAuthorizationInfo} 204 * method invocations. 205 * All future calls to {@code getAuthorizationInfo} will attempt to use this cache first 206 * to alleviate any potentially unnecessary calls to an underlying data store.</li> 207 * <li>If the {@link #setAuthorizationCache cache} property has <b>not</b> been set, 208 * the {@link #setCacheManager cacheManager} property will be checked. 209 * If a {@code cacheManager} has been set, it will be used to create an authorization 210 * {@code cache}, and this newly created cache which will be used as specified in #1.</li> 211 * <li>If neither the {@link #setAuthorizationCache (org.apache.shiro.cache.Cache) cache} 212 * or {@link #setCacheManager(org.apache.shiro.cache.CacheManager) cacheManager} 213 * properties are set, caching will be disabled and authorization look-ups will be delegated to 214 * subclass implementations for each authorization check.</li> 215 * </ol> 216 */ 217 protected void onInit() { 218 super.onInit(); 219 //trigger obtaining the authorization cache if possible 220 getAvailableAuthorizationCache(); 221 } 222 223 protected void afterCacheManagerSet() { 224 super.afterCacheManagerSet(); 225 //trigger obtaining the authorization cache if possible 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 * Returns an account's authorization-specific information for the specified {@code principals}, 267 * or {@code null} if no account could be found. The resulting {@code AuthorizationInfo} object is used 268 * by the other method implementations in this class to automatically perform access control checks for the 269 * corresponding {@code Subject}. 270 * <p/> 271 * This implementation obtains the actual {@code AuthorizationInfo} object from the subclass's 272 * implementation of 273 * {@link #doGetAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection) doGetAuthorizationInfo}, and then 274 * caches it for efficient reuse if caching is enabled (see below). 275 * <p/> 276 * Invocations of this method should be thought of as completely orthogonal to acquiring 277 * {@link #getAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken) authenticationInfo}, since either could 278 * occur in any order. 279 * <p/> 280 * For example, in "Remember Me" scenarios, the user identity is remembered (and 281 * assumed) for their current session and an authentication attempt during that session might never occur. 282 * But because their identity would be remembered, that is sufficient enough information to call this method to 283 * execute any necessary authorization checks. For this reason, authentication and authorization should be 284 * loosely coupled and not depend on each other. 285 * <h3>Caching</h3> 286 * The {@code AuthorizationInfo} values returned from this method are cached for efficient reuse 287 * if caching is enabled. Caching is enabled automatically when an {@link #setAuthorizationCache authorizationCache} 288 * instance has been explicitly configured, or if a {@link #setCacheManager cacheManager} has been configured, which 289 * will be used to lazily create the {@code authorizationCache} as needed. 290 * <p/> 291 * If caching is enabled, the authorization cache will be checked first and if found, will return the cached 292 * {@code AuthorizationInfo} immediately. If caching is disabled, or there is a cache miss, the authorization 293 * info will be looked up from the underlying data store via the 294 * {@link #doGetAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection)} method, which must be implemented 295 * by subclasses. 296 * <h4>Changed Data</h4> 297 * If caching is enabled and if any authorization data for an account is changed at 298 * runtime, such as adding or removing roles and/or permissions, the subclass implementation should clear the 299 * cached AuthorizationInfo for that account via the 300 * {@link #clearCachedAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection) clearCachedAuthorizationInfo} 301 * method. This ensures that the next call to {@code getAuthorizationInfo(PrincipalCollection)} will 302 * acquire the account's fresh authorization data, where it will then be cached for efficient reuse. This 303 * ensures that stale authorization data will not be reused. 304 * 305 * @param principals the corresponding Subject's identifying principals with which to look up the Subject's 306 * {@code AuthorizationInfo}. 307 * @return the authorization information for the account associated with the specified {@code principals}, 308 * or {@code null} if no account could be found. 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 // Call template method if the info was not found in a cache 341 info = doGetAuthorizationInfo(principals); 342 // If the info is not null and the cache has been created, then cache the authorization info. 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 * Clears out the AuthorizationInfo cache entry for the specified account. 361 * <p/> 362 * This method is provided as a convenience to subclasses so they can invalidate a cache entry when they 363 * change an account's authorization data (add/remove roles or permissions) during runtime. Because an account's 364 * AuthorizationInfo can be cached, there needs to be a way to invalidate the cache for only that account so that 365 * subsequent authorization operations don't used the (old) cached value if account data changes. 366 * <p/> 367 * After this method is called, the next authorization check for that same account will result in a call to 368 * {@link #getAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection) getAuthorizationInfo}, and the 369 * resulting return value will be cached before being returned so it can be reused for later authorization checks. 370 * <p/> 371 * If you wish to clear out all associated cached data (and not just authorization data), use the 372 * {@link #clearCache(org.apache.shiro.subject.PrincipalCollection)} method instead (which will in turn call this 373 * method by default). 374 * 375 * @param principals the principals of the account for which to clear the cached AuthorizationInfo. 376 */ 377 protected void clearCachedAuthorizationInfo(PrincipalCollection principals) { 378 if (principals == null) { 379 return; 380 } 381 382 Cache<Object, AuthorizationInfo> cache = getAvailableAuthorizationCache(); 383 //cache instance will be non-null if caching is enabled: 384 if (cache != null) { 385 Object key = getAuthorizationCacheKey(principals); 386 cache.remove(key); 387 } 388 } 389 390 /** 391 * Retrieves the AuthorizationInfo for the given principals from the underlying data store. When returning 392 * an instance from this method, you might want to consider using an instance of 393 * {@link org.apache.shiro.authz.SimpleAuthorizationInfo SimpleAuthorizationInfo}, as it is suitable in most cases. 394 * 395 * @param principals the primary identifying principals of the AuthorizationInfo that should be retrieved. 396 * @return the AuthorizationInfo associated with this principals. 397 * @see org.apache.shiro.authz.SimpleAuthorizationInfo 398 */ 399 protected abstract AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals); 400 401 //visibility changed from private to protected per SHIRO-332 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 //visibility changed from private to protected per SHIRO-332 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 * Calls {@code super.doClearCache} to ensure any cached authentication data is removed and then calls 652 * {@link #clearCachedAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection)} to remove any cached 653 * authorization data. 654 * <p/> 655 * If overriding in a subclass, be sure to call {@code super.doClearCache} to ensure this behavior is maintained. 656 * 657 * @param principals the principals of the account for which to clear any cached AuthorizationInfo 658 * @since 1.2 659 */ 660 @Override 661 protected void doClearCache(PrincipalCollection principals) { 662 super.doClearCache(principals); 663 clearCachedAuthorizationInfo(principals); 664 } 665 }
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.subject.PrincipalCollection; 22 23 import java.util.Collection; 24 import java.util.List; 25 26 /** 27 * An <tt>Authorizer</tt> performs authorization (access control) operations for any given Subject 28 * (aka 'application user'). 29 * 30 * <p>Each method requires a subject principal to perform the action for the corresponding Subject/user. 31 * 32 * <p>This principal argument is usually an object representing a user database primary key or a String username or 33 * something similar that uniquely identifies an application user. The runtime value of the this principal 34 * is application-specific and provided by the application's configured Realms. 35 * 36 * <p>Note that there are many *Permission methods in this interface overloaded to accept String arguments instead of 37 * {@link Permission Permission} instances. They are a convenience allowing the caller to use a String representation of 38 * a {@link Permission Permission} if desired. Most implementations of this interface will simply convert these 39 * String values to {@link Permission Permission} instances and then just call the corresponding type-safe method. 40 * (Shiro's default implementations do String-to-Permission conversion for these methods using 41 * {@link org.apache.shiro.authz.permission.PermissionResolver PermissionResolver}s.) 42 * 43 * <p>These overloaded *Permission methods <em>do</em> forego type-safety for the benefit of convenience and simplicity, 44 * so you should choose which ones to use based on your preferences and needs. 45 * 46 * @since 0.1 47 */ 48 public interface Authorizer { 49 50 /** 51 * Returns <tt>true</tt> if the corresponding subject/user is permitted to perform an action or access a resource 52 * summarized by the specified permission string. 53 * 54 * <p>This is an overloaded method for the corresponding type-safe {@link Permission Permission} variant. 55 * Please see the class-level JavaDoc for more information on these String-based permission methods. 56 * 57 * @param principals the application-specific subject/user identifier. 58 * @param permission the String representation of a Permission that is being checked. 59 * @return true if the corresponding Subject/user is permitted, false otherwise. 60 * @see #isPermitted(PrincipalCollection principals,Permission permission) 61 * @since 0.9 62 */ 63 boolean isPermitted(PrincipalCollection principals, String permission); 64 65 /** 66 * Returns <tt>true</tt> if the corresponding subject/user is permitted to perform an action or access a resource 67 * summarized by the specified permission. 68 * 69 * <p>More specifically, this method determines if any <tt>Permission</tt>s associated 70 * with the subject {@link Permission#implies(Permission) imply} the specified permission. 71 * 72 * @param subjectPrincipal the application-specific subject/user identifier. 73 * @param permission the permission that is being checked. 74 * @return true if the corresponding Subject/user is permitted, false otherwise. 75 */ 76 boolean isPermitted(PrincipalCollection subjectPrincipal, Permission permission); 77 78 /** 79 * Checks if the corresponding Subject implies the given permission strings and returns a boolean array 80 * indicating which permissions are implied. 81 * 82 * <p>This is an overloaded method for the corresponding type-safe {@link Permission Permission} variant. 83 * Please see the class-level JavaDoc for more information on these String-based permission methods. 84 * 85 * @param subjectPrincipal the application-specific subject/user identifier. 86 * @param permissions the String representations of the Permissions that are being checked. 87 * @return an array of booleans whose indices correspond to the index of the 88 * permissions in the given list. A true value at an index indicates the user is permitted for 89 * for the associated <tt>Permission</tt> string in the list. A false value at an index 90 * indicates otherwise. 91 * @since 0.9 92 */ 93 boolean[] isPermitted(PrincipalCollection subjectPrincipal, String... permissions); 94 95 /** 96 * Checks if the corresponding Subject/user implies the given Permissions and returns a boolean array indicating 97 * which permissions are implied. 98 * 99 * <p>More specifically, this method should determine if each <tt>Permission</tt> in 100 * the array is {@link Permission#implies(Permission) implied} by permissions 101 * already associated with the subject. 102 * 103 * <p>This is primarily a performance-enhancing method to help reduce the number of 104 * {@link #isPermitted} invocations over the wire in client/server systems. 105 * 106 * @param subjectPrincipal the application-specific subject/user identifier. 107 * @param permissions the permissions that are being checked. 108 * @return an array of booleans whose indices correspond to the index of the 109 * permissions in the given list. A true value at an index indicates the user is permitted for 110 * for the associated <tt>Permission</tt> object in the list. A false value at an index 111 * indicates otherwise. 112 */ 113 boolean[] isPermitted(PrincipalCollection subjectPrincipal, List<Permission> permissions); 114 115 /** 116 * Returns <tt>true</tt> if the corresponding Subject/user implies all of the specified permission strings, 117 * <tt>false</tt> otherwise. 118 * 119 * <p>This is an overloaded method for the corresponding type-safe {@link Permission Permission} variant. 120 * Please see the class-level JavaDoc for more information on these String-based permission methods. 121 * 122 * @param subjectPrincipal the application-specific subject/user identifier. 123 * @param permissions the String representations of the Permissions that are being checked. 124 * @return true if the user has all of the specified permissions, false otherwise. 125 * @see #isPermittedAll(PrincipalCollection,Collection) 126 * @since 0.9 127 */ 128 boolean isPermittedAll(PrincipalCollection subjectPrincipal, String... permissions); 129 130 /** 131 * Returns <tt>true</tt> if the corresponding Subject/user implies all of the specified permissions, <tt>false</tt> 132 * otherwise. 133 * 134 * <p>More specifically, this method determines if all of the given <tt>Permission</tt>s are 135 * {@link Permission#implies(Permission) implied by} permissions already associated with the subject. 136 * 137 * @param subjectPrincipal the application-specific subject/user identifier. 138 * @param permissions the permissions to check. 139 * @return true if the user has all of the specified permissions, false otherwise. 140 */ 141 boolean isPermittedAll(PrincipalCollection subjectPrincipal, Collection<Permission> permissions); 142 143 /** 144 * Ensures the corresponding Subject/user implies the specified permission String. 145 * 146 * <p>If the subject's existing associated permissions do not {@link Permission#implies(Permission)} imply} 147 * the given permission, an {@link AuthorizationException} will be thrown. 148 * 149 * <p>This is an overloaded method for the corresponding type-safe {@link Permission Permission} variant. 150 * Please see the class-level JavaDoc for more information on these String-based permission methods. 151 * 152 * @param subjectPrincipal the application-specific subject/user identifier. 153 * @param permission the String representation of the Permission to check. 154 * @throws AuthorizationException 155 * if the user does not have the permission. 156 * @since 0.9 157 */ 158 void checkPermission(PrincipalCollection subjectPrincipal, String permission) throws AuthorizationException; 159 160 /** 161 * Ensures a subject/user {@link Permission#implies(Permission)} implies} the specified <tt>Permission</tt>. 162 * If the subject's existing associated permissions do not {@link Permission#implies(Permission)} imply} 163 * the given permission, an {@link AuthorizationException} will be thrown. 164 * 165 * @param subjectPrincipal the application-specific subject/user identifier. 166 * @param permission the Permission to check. 167 * @throws AuthorizationException 168 * if the user does not have the permission. 169 */ 170 void checkPermission(PrincipalCollection subjectPrincipal, Permission permission) throws AuthorizationException; 171 172 /** 173 * Ensures the corresponding Subject/user 174 * {@link Permission#implies(Permission) implies} all of the 175 * specified permission strings. 176 * 177 * If the subject's existing associated permissions do not 178 * {@link Permission#implies(Permission) imply} all of the given permissions, 179 * an {@link AuthorizationException} will be thrown. 180 * 181 * <p>This is an overloaded method for the corresponding type-safe {@link Permission Permission} variant. 182 * Please see the class-level JavaDoc for more information on these String-based permission methods. 183 * 184 * @param subjectPrincipal the application-specific subject/user identifier. 185 * @param permissions the string representations of Permissions to check. 186 * @throws AuthorizationException if the user does not have all of the given permissions. 187 * @since 0.9 188 */ 189 void checkPermissions(PrincipalCollection subjectPrincipal, String... permissions) throws AuthorizationException; 190 191 /** 192 * Ensures the corresponding Subject/user 193 * {@link Permission#implies(Permission) implies} all of the 194 * specified permission strings. 195 * 196 * If the subject's existing associated permissions do not 197 * {@link Permission#implies(Permission) imply} all of the given permissions, 198 * an {@link AuthorizationException} will be thrown. 199 * 200 * @param subjectPrincipal the application-specific subject/user identifier. 201 * @param permissions the Permissions to check. 202 * @throws AuthorizationException if the user does not have all of the given permissions. 203 */ 204 void checkPermissions(PrincipalCollection subjectPrincipal, Collection<Permission> permissions) throws AuthorizationException; 205 206 /** 207 * Returns <tt>true</tt> if the corresponding Subject/user has the specified role, <tt>false</tt> otherwise. 208 * 209 * @param subjectPrincipal the application-specific subject/user identifier. 210 * @param roleIdentifier the application-specific role identifier (usually a role id or role name). 211 * @return <tt>true</tt> if the corresponding subject has the specified role, <tt>false</tt> otherwise. 212 */ 213 boolean hasRole(PrincipalCollection subjectPrincipal, String roleIdentifier); 214 215 /** 216 * Checks if the corresponding Subject/user has the specified roles, returning a boolean array indicating 217 * which roles are associated with the given subject. 218 * 219 * <p>This is primarily a performance-enhancing method to help reduce the number of 220 * {@link #hasRole} invocations over the wire in client/server systems. 221 * 222 * @param subjectPrincipal the application-specific subject/user identifier. 223 * @param roleIdentifiers the application-specific role identifiers to check (usually role ids or role names). 224 * @return an array of booleans whose indices correspond to the index of the 225 * roles in the given identifiers. A true value indicates the user has the 226 * role at that index. False indicates the user does not have the role at that index. 227 */ 228 boolean[] hasRoles(PrincipalCollection subjectPrincipal, List<String> roleIdentifiers); 229 230 /** 231 * Returns <tt>true</tt> if the corresponding Subject/user has all of the specified roles, <tt>false</tt> otherwise. 232 * 233 * @param subjectPrincipal the application-specific subject/user identifier. 234 * @param roleIdentifiers the application-specific role identifiers to check (usually role ids or role names). 235 * @return true if the user has all the roles, false otherwise. 236 */ 237 boolean hasAllRoles(PrincipalCollection subjectPrincipal, Collection<String> roleIdentifiers); 238 239 /** 240 * Asserts the corresponding Subject/user has the specified role by returning quietly if they do or throwing an 241 * {@link AuthorizationException} if they do not. 242 * 243 * @param subjectPrincipal the application-specific subject/user identifier. 244 * @param roleIdentifier the application-specific role identifier (usually a role id or role name ). 245 * @throws AuthorizationException 246 * if the user does not have the role. 247 */ 248 void checkRole(PrincipalCollection subjectPrincipal, String roleIdentifier) throws AuthorizationException; 249 250 /** 251 * Asserts the corresponding Subject/user has all of the specified roles by returning quietly if they do or 252 * throwing an {@link AuthorizationException} if they do not. 253 * 254 * @param subjectPrincipal the application-specific subject/user identifier. 255 * @param roleIdentifiers the application-specific role identifiers to check (usually role ids or role names). 256 * @throws AuthorizationException 257 * if the user does not have all of the specified roles. 258 */ 259 void checkRoles(PrincipalCollection subjectPrincipal, Collection<String> roleIdentifiers) throws AuthorizationException; 260 261 /** 262 * Same as {@link #checkRoles(org.apache.shiro.subject.PrincipalCollection, java.util.Collection) 263 * checkRoles(PrincipalCollection subjectPrincipal, Collection<String> roleIdentifiers)} but doesn't require a collection 264 * as an argument. 265 * Asserts the corresponding Subject/user has all of the specified roles by returning quietly if they do or 266 * throwing an {@link AuthorizationException} if they do not. 267 * 268 * @param subjectPrincipal the application-specific subject/user identifier. 269 * @param roleIdentifiers the application-specific role identifiers to check (usually role ids or role names). 270 * @throws AuthorizationException 271 * if the user does not have all of the specified roles. 272 * 273 * @since 1.1.0 274 */ 275 void checkRoles(PrincipalCollection subjectPrincipal, String... roleIdentifiers) throws AuthorizationException; 276 277 }
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.permission; 20 21 /** 22 * Interface implemented by a component that wishes to use any application-configured <tt>PermissionResolver</tt> that 23 * might already exist instead of potentially creating one itself. 24 * 25 * <p>This is mostly implemented by {@link org.apache.shiro.authz.Authorizer Authorizer} and 26 * {@link org.apache.shiro.realm.Realm Realm} implementations since they 27 * are the ones performing permission checks and need to know how to resolve Strings into 28 * {@link org.apache.shiro.authz.Permission Permission} instances. 29 * 30 * @since 0.9 31 */ 32 public interface PermissionResolverAware { 33 34 /** 35 * Sets the specified <tt>PermissionResolver</tt> on this instance. 36 * 37 * @param pr the <tt>PermissionResolver</tt> being set. 38 */ 39 public void setPermissionResolver(PermissionResolver pr); 40 }
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.permission; 20 21 /** 22 * Interface implemented by a component that wishes to use any application-configured <tt>RolePermissionResolver</tt> that 23 * might already exist instead of potentially creating one itself. 24 * 25 * <p>This is mostly implemented by {@link org.apache.shiro.authz.Authorizer Authorizer} and 26 * {@link org.apache.shiro.realm.Realm Realm} implementations since they 27 * are the ones performing permission checks and need to know how to resolve Strings into 28 * {@link org.apache.shiro.authz.Permission Permission} instances. 29 * 30 * @since 1.0 31 */ 32 public interface RolePermissionResolverAware { 33 34 /** 35 * Sets the specified <tt>RolePermissionResolver</tt> on this instance. 36 * 37 * @param rpr the <tt>RolePermissionResolver</tt> being set. 38 */ 39 public void setRolePermissionResolver(RolePermissionResolver rpr); 40 }
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.permission; 20 21 import org.apache.shiro.authz.Permission; 22 23 import java.util.Collection; 24 25 /** 26 * A RolePermissionResolver resolves a String value and converts it into a Collection of 27 * {@link org.apache.shiro.authz.Permission} instances. 28 * <p/> 29 * In some cases a {@link org.apache.shiro.realm.Realm} my only be able to return a list of roles. This 30 * component allows an application to resolve the roles into permissions. 31 * 32 */ 33 public interface RolePermissionResolver { 34 35 /** 36 * Resolves a Collection of Permissions based on the given String representation. 37 * 38 * @param roleString the String representation of a role name to resolve. 39 * @return a Collection of Permissions based on the given String representation. 40 */ 41 Collection<Permission> resolvePermissionsInRole(String roleString); 42 43 }