1、关于shiro的Realm权限执行原理的理解:
1.1、继承AuthorizingRealm定义自己的Realm,realm里面的doGetAuthenticationInfo(AuthenticationToken token)
方法是在登录时候做验证,根据token获取用户提交的用户名,然后到数据库查找是否存在该用户,存在则new一个SimpleAuthenticationInfo对象,然后交由给CredentialsMatcher的doCredentialsMatch方法,去匹配密码是否一致。
1.2、当访问有权限限制的url或资源的时候,会调用doGetAuthorizationInfo(PrincipalCollection principals)
,该方法也是返回一个预先设置好了role、permission的SimpleAuthorizationInfo,然后判断当前访问的资源需要的权限,是否在SimpleAuthorizationInfo里面。在每次访问有权限的资源(加了@RequiresPermissions,或者url在shiroFilter的filterChainDefinitions里面,有role,perm的资源,如user/* = role[user],user/*=perm[user:*])的时候都会调用,所以可以考虑将realm里面的授权信息放在缓存里面,避免每次访问数据库。
2、授权信息配置在缓存中:
配合ehcache使用,spring-shiro.xml:
<bean id="myRealm" class="com.sz.pos.shiro.realm.MyRealm">
<property name="credentialsMatcher" ref="credentialsMatcher" />
<property name="cachingEnabled" value="false" />
<!-- 如需要自定义缓存时间放开以下.修改 ehcache.xml -->
<property name="authenticationCachingEnabled" value="true" />
<property name="authenticationCacheName" value="authenticationCache" />
<property name="authorizationCachingEnabled" value="true" />
<property name="authorizationCacheName" value="authorizationCache" />
</bean>
<!-- shiro缓存管理器 -->
<bean id="cacheManager" class="com.sz.pos.shiro.spring.SpringCacheManagerWrapper">
<property name="cacheManager" ref="springCacheManager" />
</bean>
<bean id="springCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="ehcacheManager" />
</bean>
<!--ehcache -->
<bean id="ehcacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:config/ehcache.xml" />
</bean>
ehcache.xml增加如下配置:
<cache name="authorizationCache" maxEntriesLocalHeap="2000"
eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="0"
overflowToDisk="false" statistics="true">
</cache>
<cache name="authenticationCache" maxEntriesLocalHeap="2000"
eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="0"
overflowToDisk="false" statistics="true">
</cache>
编写实现了CacheManager接口的SpringCacheManagerWrapper类:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.cache.support.SimpleValueWrapper;
import net.sf.ehcache.Ehcache;
public class SpringCacheManagerWrapper implements CacheManager {
private org.springframework.cache.CacheManager cacheManager;
/**
* 设置spring cache manager
*
* @param cacheManager
*/
public void setCacheManager(org.springframework.cache.CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
public <K, V> Cache<K, V> getCache(String name) throws CacheException {
org.springframework.cache.Cache springCache = cacheManager.getCache(name);
return new SpringCacheWrapper(springCache);
}
static class SpringCacheWrapper implements Cache {
private org.springframework.cache.Cache springCache;
SpringCacheWrapper(org.springframework.cache.Cache springCache) {
this.springCache = springCache;
}
public Object get(Object key) throws CacheException {
Object value = springCache.get(key);
if (value instanceof SimpleValueWrapper) {
return ((SimpleValueWrapper) value).get();
}
return value;
}
public Object put(Object key, Object value) throws CacheException {
springCache.put(key, value);
return value;
}
public Object remove(Object key) throws CacheException {
springCache.evict(key);
return null;
}
public void clear() throws CacheException {
springCache.clear();
}
public int size() {
if (springCache.getNativeCache() instanceof Ehcache) {
Ehcache ehcache = (Ehcache) springCache.getNativeCache();
return ehcache.getSize();
}
throw new UnsupportedOperationException("invoke spring cache abstract size method not supported");
}
public Set keys() {
if (springCache.getNativeCache() instanceof Ehcache) {
Ehcache ehcache = (Ehcache) springCache.getNativeCache();
return new HashSet(ehcache.getKeys());
}
throw new UnsupportedOperationException("invoke spring cache abstract keys method not supported");
}
public Collection values() {
if (springCache.getNativeCache() instanceof Ehcache) {
Ehcache ehcache = (Ehcache) springCache.getNativeCache();
List keys = ehcache.getKeys();
if (!CollectionUtils.isEmpty(keys)) {
List values = new ArrayList(keys.size());
for (Object key : keys) {
Object value = get(key);
if (value != null) {
values.add(value);
}
}
return Collections.unmodifiableList(values);
} else {
return Collections.emptyList();
}
}
throw new UnsupportedOperationException("invoke spring cache abstract values method not supported");
}
}
}