shiro cache instance code

  • 2020-06-15 10:59:45
  • OfStack

Shiro provides Cache abstraction similar to Spring, that is, Shiro does not implement Cache itself, but abstracts Cache to facilitate the replacement of different underlying Cache implementations.

Cache Interface provided by Shiro:

Java code


public interface Cache<K, V> { 
 // According to the Key Gets the value in the cache  
 public V get(K key) throws CacheException; 
 // Put it in the cache key-value , returns the previous value in the cache  
 public V put(K key, V value) throws CacheException; 
 // Remove from cache key Returns the corresponding value  
 public V remove(K key) throws CacheException; 
 // Clear the entire cache  
 public void clear() throws CacheException; 
 // Return cache size  
 public int size(); 
 // Gets all of the items in the cache key 
 public Set<K> keys(); 
 // Gets all of the items in the cache value 
 public Collection<V> values(); 
} 

CacheManager interface provided by Shiro:

Java code


public interface CacheManager { 
 // Gets by the cache name 1 a Cache 
 public <K, V> Cache<K, V> getCache(String name) throws CacheException; 
} 

Shiro also provides CacheManagerAware for injecting CacheManager:

Java code


public interface CacheManagerAware { 
 // injection CacheManager 
 void setCacheManager(CacheManager cacheManager); 
} 

The corresponding component within Shiro (DefaultSecurityManager) automatically detects whether the corresponding object (such as Realm) implements CacheManagerAware and infuses the corresponding CacheManager automatically.

Realm cache

Shiro provides CachingRealm, which implements CacheManagerAware interface and provides some basic implementations of caching. In addition, AuthenticatingRealm and AuthorizingRealm provide caching of AuthenticationInfo and AuthorizationInfo information, respectively.

ini configuration

Java code


userRealm=com.github.zhangkaitao.shiro.chapter11.realm.UserRealm 
userRealm.credentialsMatcher=$credentialsMatcher 
userRealm.cachingEnabled=true 
userRealm.authenticationCachingEnabled=true 
userRealm.authenticationCacheName=authenticationCache
userRealm.authorizationCachingEnabled=true 
userRealm.authorizationCacheName=authorizationCache 
securityManager.realms=$userRealm 
cacheManager=org.apache.shiro.cache.ehcache.EhCacheManager 
cacheManager.cacheManagerConfigFile=classpath:shiro-ehcache.xml 
securityManager.cacheManager=$cacheManager 

userRealm. cachingEnabled: Enable cache, default false;
userRealm. authenticationCachingEnabled: Enable authentication cache, that is, cache AuthenticationInfo information, default false;
userRealm.authenticationCacheName: Cache name of AuthenticationInfo information;
userRealm. authorizationCachingEnabled: Enable authorization cache, that is, cache AuthorizationInfo information, default false;
userRealm. authorizationCacheName: Cache name for AuthorizationInfo information;

cacheManager: Cache manager, EhCacheManager, Ehcache implementation, need to import the corresponding Ehcache dependencies, please refer to pom.xml;

Due to test cases, CacheManager of Ehcache needs to be changed to use VM singleton mode:


this.manager = new net.sf.ehcache.CacheManager(getCacheManagerConfigFileInputStream());

Instead of


this.manager = net.sf.ehcache.CacheManager.create(getCacheManagerConfigFileInputStream()); 

The test case

Java code


@Test 
public void testClearCachedAuthenticationInfo() { 
 login(u1.getUsername(), password); 
 userService.changePassword(u1.getId(), password + "1"); 
 
 RealmSecurityManager securityManager = 
  (RealmSecurityManager) SecurityUtils.getSecurityManager(); 
 UserRealm userRealm = (UserRealm) securityManager.getRealms().iterator().next(); 
 userRealm.clearCachedAuthenticationInfo(subject().getPrincipals()); 
 login(u1.getUsername(), password + "1"); 
} 

First, the login is successful (the corresponding AuthenticationInfo will be cached at this time), and then the password will be changed. The password changes; Then you need to call the clearCachedAuthenticationInfo method of Realm to clear the previously cached AuthenticationInfo. Otherwise, the next time you log in, you will get the same AuthenticationInfo as before you changed your password.

Java code


@Test 
public void testClearCachedAuthorizationInfo() { 
 login(u1.getUsername(), password); 
 subject().checkRole(r1.getRole()); 
 userService.correlationRoles(u1.getId(), r2.getId()); 
 
 RealmSecurityManager securityManager = 
  (RealmSecurityManager) SecurityUtils.getSecurityManager(); 
 UserRealm userRealm = (UserRealm)securityManager.getRealms().iterator().next(); 
 userRealm.clearCachedAuthorizationInfo(subject().getPrincipals()); 
 subject().checkRole(r2.getRole()); 
} 

Similar to the previous use case; Call Realm's clearCachedAuthorizationInfo here to clear the previously cached AuthorizationInfo;

There is also clearCache, which calls both clearCachedAuthenticationInfo and clearCachedAuthorizationInfo, emptying both AuthenticationInfo and AuthorizationInfo.

UserRealm also provides clearAllCachedAuthorizationInfo, clearAllCachedAuthenticationInfo, clearAllCache for clearing the entire cache.

In some cases, this may not be the best choice. Consider discarding Shiro's cache directly and implementing your own cache through AOP. For reference:

https://github.com/zhangkaitao/es/tree/master/web/src/main/java/com/sishuok/es/extra/aop

In addition, when integrating with Spring, it can be considered to directly use Cache abstraction of Spring. SpringCacheManagerWrapper can be used to package Spring Cache and convert it to CacheManager implementation of Shiro:

https://github.com/zhangkaitao/es/blob/master/web/src/main/java/org/apache/shiro/cache/spring/SpringCacheManagerWrapper.java

Session cache

When we set CacheManager of SecurityManager, such as:

Java code


securityManager.cacheManager=$cacheManager 

When we set SessionManager:

Java code


sessionManager=org.apache.shiro.session.mgt.DefaultSessionManager 
securityManager.sessionManager=$sessionManager 

If securityManager implements SessionsSecurityManager, it will automatically determine whether SessionManager implements the CacheManagerAware interface and set CacheManager to it if it does. sessionManager then determines whether the corresponding sessionDAO (for example, inherited from CachingSessionDAO) implements CacheManagerAware and sets CacheManager to it if it does. MySessionDAO in Chapter 9 is SessionDAO with cache; It will check the cache first and the database only if it cannot be found.

For CachingSessionDAO, the name of the cache can be set using the following configuration:

Java code


public interface CacheManager { 
 // Gets by the cache name 1 a Cache 
 public <K, V> Cache<K, V> getCache(String name) throws CacheException; 
} 
0

conclusion


Related articles: