本文最后更新于 1630 天前,其中的信息可能已经有所发展或是发生改变。
缓存管理就是把一些权限数据交给Redis,这里就不用重复的从数据库中拿到权限数据,进而提高效率。本文的只提供部分的代码,在Shiro会话管理基础上作扩充。
1.创建自定义缓存Manager。
package com.benzhu.shiro.cache;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component("cacheManager")
public class RedisCacheManager implements CacheManager {
@Resource
private RedisCache redisCache;
@Override
public <K, V> Cache<K, V> getCache(String name) throws CacheException {
return redisCache;
}
}
2.创建缓存的增删查改。
package com.benzhu.shiro.cache;
import com.benzhu.shiro.config.RedisConfig;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.stereotype.Component;
import org.springframework.util.SerializationUtils;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.Set;
@Component
public class RedisCache<k,v> implements Cache<k,v> {
@Resource
private RedisConfig redisConfig;
private final String CACHE_PREFIX = "imooc-cache:";
private byte[] getkey(k k){
if(k instanceof String){
//判断K值是否为String类型 不是就直接返回序列化数组
return (CACHE_PREFIX +k).getBytes();
}
return SerializationUtils.serialize(k);
}
@Override
public v get(k key) throws CacheException {
//查询
System.out.println("从缓存中读取数据。");
byte[] val = redisConfig.get(getkey(key));
if(val != null){
return (v) SerializationUtils.deserialize(val);
}
return null;
}
@Override
public v put(k key, v value) throws CacheException {
//增加
byte[] k = getkey(key);
byte[] val = SerializationUtils.serialize(value);
redisConfig.set(k, val);
redisConfig.expire(k, 600);
return value;
}
@Override
public v remove(k key) throws CacheException {
//删除
byte[] k = getkey(key);
byte[] val = redisConfig.get(k);
redisConfig.del(k);
if(val != null){
return (v) SerializationUtils.deserialize(val);
}
return null;
}
@Override
public void clear() throws CacheException {
//不要重写 等下把Redis的所有数据都清空了
}
@Override
public int size() {
//返回数量
return 0;
}
@Override
public Set<k> keys() {
//查询全部key
return null;
}
@Override
public Collection<v> values() {
//查询全部
return null;
}
}
3.配置自定义的CacheManager。
package com.benzhu.shiro.Filter;
import com.benzhu.shiro.cache.RedisCacheManager;
import com.benzhu.shiro.realm.CustomRealm;
import com.benzhu.shiro.session.CustomSessionManager;
import com.benzhu.shiro.session.RedisSessionDao;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfiguration {
@Resource(name = "realm")
private CustomRealm customRealm;
@Resource(name = "redisSessionDao")
private RedisSessionDao redisSessionDao;
@Resource
private RedisCacheManager redisCacheManager;
@Bean(name="shiroFilter")
public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") DefaultWebSecurityManager manager) {
ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean();
bean.setSecurityManager(manager);
//配置登录的url和登录成功的url以及验证失败的url
bean.setLoginUrl("/login");
bean.setUnauthorizedUrl("/error");
//配置自定义的Filter
Map<String, Filter> filtersMap = new LinkedHashMap<String, Filter>();
filtersMap.put("roleOrFilter", new RolesOrFilter());
bean.setFilters(filtersMap);
//配置访问权限
LinkedHashMap<String, String> filterChainDefinitionMap=new LinkedHashMap<>();
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/sublogin", "anon");
filterChainDefinitionMap.put("/usererror", "anon");
filterChainDefinitionMap.put("/roles1", "roles[admin]");
filterChainDefinitionMap.put("/roles2", "roles[admin,user]");
filterChainDefinitionMap.put("/permission1", "perms[user:update]");
filterChainDefinitionMap.put("/permission2", "perms[user:update,user:select]");
filterChainDefinitionMap.put("/roles3", "roleOrFilter[admin,user]");
filterChainDefinitionMap.put("/**","authc");
bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return bean;
}
//配置核心安全事务管理器
@Bean(name="securityManager")
public DefaultWebSecurityManager securityManager(@Qualifier("sessionManager")CustomSessionManager sessionManager) {
DefaultWebSecurityManager manager=new DefaultWebSecurityManager();
//配置自定义Realm
manager.setRealm(customRealm);
//配置自定义sessionManager
manager.setSessionManager(sessionManager);
//配置自定义cacheManager,主要添加的就是底下这行
manager.setCacheManager(redisCacheManager);
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(); //创建加密对象
matcher.setHashAlgorithmName("md5"); //加密的算法
matcher.setHashIterations(1);//加密次数
customRealm.setCredentialsMatcher(matcher); //放入自定义Realm
return manager;
}
//以下是开启注解支持
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
//配置session
@Bean(name="sessionManager")
public CustomSessionManager sessionManager(){
//把sessionManager注入Bean
CustomSessionManager manager = new CustomSessionManager();
manager.setSessionDAO(redisSessionDao);
return manager;
}
}
4.测试图。
登陆后访问一个页面,从图中可以看出,在第二次访问刷新的时候就不会从数据库读取了。