zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    codeforces 439C 模拟
    codeforces 435B
    【WebVR】AFrame中的A-sky无法利用src指定路径显示全景图
    【UE4】添加头文件之后VS中UCLASS()报错问题解决办法
    【UE4】蓝图之间的通讯
    git中报unable to auto-detect email address 错误的解决办法
    2017ACM省赛总结与生涯回顾
    hihocoder#1121 : 二分图一•二分图判定
    hihocoder#1039 : 字符消除
    2048low版
  • 原文地址:https://www.cnblogs.com/scmath/p/9818170.html
Copyright © 2011-2022 走看看