继上一篇 Springboot2 + Shiro + Redis + Jwt 前后端分离整合(3) 继续补充
码云项目地址 : Springboot + shiro + redis + jwt + jpa
使用自己的redis缓存机制
重写redisCache—CustimCache类
@Slf4j
public class CustomCache<K,V> implements Cache<K,V> {
/**
* 缓存的key名称获取为shiro:cache:account
* @param key
*/
private String getKey(K key) {
String userId;
if (key instanceof PrincipalCollection) {
UserEntity user = (UserEntity) ((PrincipalCollection)key).getPrimaryPrincipal();
userId= TokenUtil.getField(user.getToken(), "userId",Long.class).toString();
} else {
userId = key.toString();
}
return ShiroConstant.ROLE_SHIRO_CACHE + userId;
}
/**
* 获取缓存
*/
@Override
public V get(K key) throws CacheException {
if (!RedisUtil.hasKey(this.getKey(key))) {
return null;
}
Object o = RedisUtil.get(this.getKey(key));
V v = (V)o;
return (V)o;
}
/**
* 保存缓存
*/
@Override
public V put(K key, V value) throws CacheException {
RedisUtil.set(this.getKey(key), value);
return value;
}
/**
* 移除缓存
*/
@Override
public V remove(K key) throws CacheException {
if (!RedisUtil.hasKey(this.getKey(key))) {
return null;
}
RedisUtil.del(this.getKey(key));
return null;
}
/**
* 清空所有缓存
*/
@Override
public void clear() throws CacheException {
}
/**
* 缓存的个数
*/
@Override
public Set<K> keys() {
return null;
}
/**
* 获取所有的key
*/
@Override
public int size() {
return 0;
}
/**
* 获取所有的value
*/
@Override
public Collection<V> values() {
return null;
}
}
缓存管理器CustomCacheManager
public class CustomCacheManager implements CacheManager {
@Override
public <K, V> Cache<K, V> getCache(String s) throws CacheException {
return new CustomCache<K, V>();
}
}
修改ShiroConfig中的securityManager方法就可以了
@Bean(name = "securityManager")
public org.apache.shiro.mgt.SecurityManager securityManager(AuthRealm realm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm);
// //使用shiro的redis缓存
// securityManager.setCacheManager(cacheManager());
//使用自己的redis缓存
securityManager.setCacheManager(new CustomCacheManager());
//关闭Shiro自带的session
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
securityManager.setSubjectDAO(subjectDAO);
return securityManager;
}
shiro登出出来的问题
因我们不使用shiro的session机制,所以不能用shiro自带的logout来清除缓存,但是单单用subject.logout(),这只会清除redis中的角色权限缓存,不会清除认证缓存!
@PostMapping("/logout")
public Map<String, Object> logout() {
Subject sub = SecurityUtils.getSubject();
// sub.logout应该放到 user获取之后,不然user获取到为空
// 这里感谢 淘气包丶 大兄弟指出问题所在
UserEntity user = (UserEntity)sub.getPrincipal();
sub.logout();
RedisUtil.del(ShiroConstant.LOGIN_SHIRO_CACHE + user.getId());
Map<String, Object> result = new HashMap<>();
result.put("status", "200");
result.put("msg", "登出成功");
return result;
}