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;

}
Realm.java
//
// 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);
}
Nameable
 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 }
CacheManagerAware
 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 }
LogoutAware.java

 

  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 }
AuthenticatingRealm.java
 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 }
Initializable
  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 &quot;Remember Me&quot; 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 }
AuthorizingRealm
  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&lt;String&gt; 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 }
Authorizer
 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 }
PermissionResolverAware
 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 }
RolePermissionResolverAware
 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 }
RolePermissionResolver

 

posted @ 2018-12-02 13:19  scmath  阅读(215)  评论(0编辑  收藏  举报