shiro中原始的RedisSessionDAO如下,keyPrefix为shiro_redis_session:,某些情况下需要自定义这个值
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.crazycake.shiro;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RedisSessionDAO extends AbstractSessionDAO {
private static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class);
private RedisManager redisManager;
private String keyPrefix = "shiro_redis_session:";
public RedisSessionDAO() {
}
public void update(Session session) throws UnknownSessionException {
this.saveSession(session);
}
private void saveSession(Session session) throws UnknownSessionException {
if (session != null && session.getId() != null) {
byte[] key = this.getByteKey(session.getId());
byte[] value = SerializeUtils.serialize(session);
session.setTimeout((long)(this.redisManager.getExpire() * 1000));
this.redisManager.set(key, value, this.redisManager.getExpire());
} else {
logger.error("session or session id is null");
}
}
public void delete(Session session) {
if (session != null && session.getId() != null) {
this.redisManager.del(this.getByteKey(session.getId()));
} else {
logger.error("session or session id is null");
}
}
public Collection getActiveSessions() {
Set sessions = new HashSet();
Set keys = this.redisManager.keys(this.keyPrefix + "*");
if (keys != null && keys.size() > 0) {
Iterator i$ = keys.iterator();
while(i$.hasNext()) {
byte[] key = (byte[])i$.next();
Session s = (Session)SerializeUtils.deserialize(this.redisManager.get(key));
sessions.add(s);
}
}
return sessions;
}
protected Serializable doCreate(Session session) {
Serializable sessionId = this.generateSessionId(session);
this.assignSessionId(session, sessionId);
this.saveSession(session);
return sessionId;
}
protected Session doReadSession(Serializable sessionId) {
if (sessionId == null) {
logger.error("session id is null");
return null;
} else {
Session s = (Session)SerializeUtils.deserialize(this.redisManager.get(this.getByteKey(sessionId)));
return s;
}
}
private byte[] getByteKey(Serializable sessionId) {
String preKey = this.keyPrefix + sessionId;
return preKey.getBytes();
}
public RedisManager getRedisManager() {
return this.redisManager;
}
public void setRedisManager(RedisManager redisManager) {
this.redisManager = redisManager;
this.redisManager.init();
}
public String getKeyPrefix() {
return this.keyPrefix;
}
public void setKeyPrefix(String keyPrefix) {
this.keyPrefix = keyPrefix;
}
}
自定义:
public class MyRedisSessionDAO extends RedisSessionDAO {
private Logger logger = LoggerFactory.getLogger(MyRedisSessionDAO.class);
private RedisManager redisManager;
//自定义key前缀
private String keyPrefix = "cmp_shiro_redis_session:";
public MyRedisSessionDAO() {
}
public void update(Session session) throws UnknownSessionException {
this.saveSession(session);
}
private void saveSession(Session session) throws UnknownSessionException {
if (session != null && session.getId() != null) {
byte[] key = this.getByteKey(session.getId());
byte[] value = SerializeUtils.serialize(session);
session.setTimeout((long)(this.redisManager.getExpire() * 1000));
this.redisManager.set(key, value, this.redisManager.getExpire());
} else {
logger.error("session or session id is null");
}
}
public void delete(Session session) {
if (session != null && session.getId() != null) {
this.redisManager.del(this.getByteKey(session.getId()));
} else {
logger.error("session or session id is null");
}
}
public Collection getActiveSessions() {
Set sessions = new HashSet();
Set keys = this.redisManager.keys(this.keyPrefix + "*");
if (keys != null && keys.size() > 0) {
Iterator i$ = keys.iterator();
while(i$.hasNext()) {
byte[] key = (byte[])i$.next();
Session s = (Session)SerializeUtils.deserialize(this.redisManager.get(key));
sessions.add(s);
}
}
return sessions;
}
protected Serializable doCreate(Session session) {
Serializable sessionId = this.generateSessionId(session);
this.assignSessionId(session, sessionId);
this.saveSession(session);
return sessionId;
}
protected Session doReadSession(Serializable sessionId) {
if (sessionId == null) {
logger.error("session id is null");
return null;
} else {
Session s = (Session) SerializeUtils.deserialize(this.redisManager.get(this.getByteKey(sessionId)));
return s;
}
}
private byte[] getByteKey(Serializable sessionId) {
String preKey = this.keyPrefix + sessionId;
return preKey.getBytes();
}
public RedisManager getRedisManager() {
return this.redisManager;
}
public void setRedisManager(RedisManager redisManager) {
this.redisManager = redisManager;
this.redisManager.init();
}
public String getKeyPrefix() {
return this.keyPrefix;
}
public void setKeyPrefix(String keyPrefix) {
this.keyPrefix = keyPrefix;
}
}
然后在DefaultWebSessionManager中
/**
* Session Manager
* 使用的是shiro-redis开源插件
*/
@Bean
public DefaultWebSessionManager sessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionDAO(redisSessionDAO());
return sessionManager;
}
redisSessionDAO()的实现
@Bean
public MyRedisSessionDAO redisSessionDAO() {
MyRedisSessionDAO redisSessionDAO = new MyRedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager());
return redisSessionDAO;
}
附上完整的ShiroConfig代码
package cn.com.suntree.cmp.config;
import cn.com.suntree.cmp.entity.Power;
import cn.com.suntree.cmp.entity.Role;
import cn.com.suntree.cmp.entity.SysUser;
import cn.com.suntree.cmp.service.CmpUserService;
import cn.com.suntree.cmp.utils.CommonUtil;
import cn.com.suntree.cmp.utils.YAMLUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.crazycake.shiro.SerializeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import javax.servlet.Filter;
import java.io.Serializable;
import java.util.*;
@Log4j2
@Configuration
public class ShiroConfig {
/**
* @Autowired
* @Lazy private SysUserService userService;
*/
@Autowired
YAMLUtils yaml;
/**
* @param securityManager
* @return 拦截工厂配置
*/
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
//自定义拦截器
Map filtersMap = new LinkedHashMap();
//限制同一帐号同时在线的个数。
filtersMap.put("kickout", kickoutSessionControlFilter());
shiroFilterFactoryBean.setFilters(filtersMap);
//权限控制map
HashMap filterMap = new LinkedHashMap<>();
filterMap.put("/api/enclosure/download", "anon");
filterMap.put("/api/register/**", "anon");
filterMap.put("/api/enclosure/onlinePreview", "anon");
filterMap.put("/api/**", "authc");
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setUnauthorizedUrl("/error");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
/**
* @return 安全管理器
*/
@Bean
public SecurityManager securityManager(@Qualifier("myShiroRealm") MyShiroRealm myShiroRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(myShiroRealm);
// 自定义缓存实现 使用redis
securityManager.setCacheManager(cacheManager());
// 自定义session管理 使用redis
securityManager.setSessionManager(sessionManager());
return securityManager;
}
/**
* 身份认证realm; (这个需要自己写,账号密码校验;权限等)
*
* @return
*/
@Bean
public MyShiroRealm myShiroRealm() {
MyShiroRealm myShiroRealm = new MyShiroRealm();
myShiroRealm.setCredentialsMatcher(credentialsMatcher());
myShiroRealm.setCacheManager(cacheManager());//設置緩存
return myShiroRealm;
}
/**
* cacheManager 缓存 redis实现
* 使用的是shiro-redis开源插件
*
* @return
*/
public RedisCacheManager cacheManager() {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager());
return redisCacheManager;
}
/**
* 配置shiro redisManager
* 使用的是shiro-redis开源插件
*
* @return
*/
public RedisManager redisManager() {
RedisManager redisManager = new RedisManager();
redisManager.setHost(yaml.redis_host);
redisManager.setPort(yaml.redis_port);
redisManager.setExpire(yaml.redis_cache);// 配置缓存过期时间
redisManager.setTimeout(0);
redisManager.setPassword(yaml.redis_passwd);
return redisManager;
}
/**
* Session Manager
* 使用的是shiro-redis开源插件
*/
@Bean
public DefaultWebSessionManager sessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionDAO(redisSessionDAO());
return sessionManager;
}
public class MyRedisSessionDAO extends RedisSessionDAO {
private Logger logger = LoggerFactory.getLogger(MyRedisSessionDAO.class);
private RedisManager redisManager;
private String keyPrefix = "cmp_shiro_redis_session:";
public MyRedisSessionDAO() {
}
public void update(Session session) throws UnknownSessionException {
this.saveSession(session);
}
private void saveSession(Session session) throws UnknownSessionException {
if (session != null && session.getId() != null) {
byte[] key = this.getByteKey(session.getId());
byte[] value = SerializeUtils.serialize(session);
session.setTimeout((long)(this.redisManager.getExpire() * 1000));
this.redisManager.set(key, value, this.redisManager.getExpire());
} else {
logger.error("session or session id is null");
}
}
public void delete(Session session) {
if (session != null && session.getId() != null) {
this.redisManager.del(this.getByteKey(session.getId()));
} else {
logger.error("session or session id is null");
}
}
public Collection getActiveSessions() {
Set sessions = new HashSet();
Set keys = this.redisManager.keys(this.keyPrefix + "*");
if (keys != null && keys.size() > 0) {
Iterator i$ = keys.iterator();
while(i$.hasNext()) {
byte[] key = (byte[])i$.next();
Session s = (Session)SerializeUtils.deserialize(this.redisManager.get(key));
sessions.add(s);
}
}
return sessions;
}
protected Serializable doCreate(Session session) {
Serializable sessionId = this.generateSessionId(session);
this.assignSessionId(session, sessionId);
this.saveSession(session);
return sessionId;
}
protected Session doReadSession(Serializable sessionId) {
if (sessionId == null) {
logger.error("session id is null");
return null;
} else {
Session s = (Session) SerializeUtils.deserialize(this.redisManager.get(this.getByteKey(sessionId)));
return s;
}
}
private byte[] getByteKey(Serializable sessionId) {
String preKey = this.keyPrefix + sessionId;
return preKey.getBytes();
}
public RedisManager getRedisManager() {
return this.redisManager;
}
public void setRedisManager(RedisManager redisManager) {
this.redisManager = redisManager;
this.redisManager.init();
}
public String getKeyPrefix() {
return this.keyPrefix;
}
public void setKeyPrefix(String keyPrefix) {
this.keyPrefix = keyPrefix;
}
}
/**
* RedisSessionDAO shiro sessionDao层的实现 通过redis
* 使用的是shiro-redis开源插件
*/
@Bean
public MyRedisSessionDAO redisSessionDAO() {
MyRedisSessionDAO redisSessionDAO = new MyRedisSessionDAO();
//自定义sessionId生成器
//redisSessionDAO.setSessionIdGenerator(mySessionIdGenerstor());
redisSessionDAO.setRedisManager(redisManager());
return redisSessionDAO;
}
/*
@Bean
public MySessionIdGenerstor mySessionIdGenerstor(){
return new MySessionIdGenerstor();
}
*/
/**
* 限制同一账号登录同时登录人数控制
*
* @return
*/
@Bean
public KickoutSessionControlFilter kickoutSessionControlFilter() {
KickoutSessionControlFilter kickoutSessionControlFilter = new KickoutSessionControlFilter();
//使用cacheManager获取相应的cache来缓存用户登录的会话;用于保存用户—会话之间的关系的;
//这里我们还是用之前shiro使用的redisManager()实现的cacheManager()缓存管理
//也可以重新另写一个,重新配置缓存时间之类的自定义缓存属性
kickoutSessionControlFilter.setCacheManager(cacheManager());
//用于根据会话ID,获取会话进行踢出操作的;
kickoutSessionControlFilter.setSessionManager(sessionManager());
//是否踢出后来登录的,默认是false;即后者登录的用户踢出前者登录的用户;踢出顺序。
kickoutSessionControlFilter.setKickoutAfter(false);
//同一个用户最大的会话数,默认1;比如2的意思是同一个用户允许最多同时两个人登录;
kickoutSessionControlFilter.setMaxSession(1);
//被踢出后重定向到的地址;
kickoutSessionControlFilter.setKickoutUrl("/kickout");
return kickoutSessionControlFilter;
}
/***
* 授权所用配置
*
* @return
*/
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
defaultAAP.setProxyTargetClass(true);
return defaultAAP;
}
/**
* @param securityManager
* @return 授权注解支持
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
/**
* Shiro生命周期处理器
@Bean public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
*/
/**
* @return 密码匹配器
*/
@Bean
public CredentialsMatcher credentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");
return hashedCredentialsMatcher;
}
/**
* 自定义 - 数据域
*/
public class MyShiroRealm extends AuthorizingRealm {
@Autowired
@Lazy
private CmpUserService userService;
//@Autowired
//private void setSysUserService(CmpUserService userService) {
//this.userService = userService;
// }
/**
* @param principalCollection
* @return
* @implNote 功能授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SysUser user = (SysUser) principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//user = userService.getUserInfoByUserId(user.getUserID());
user = userService.getUserDetailInfoByUserId(user.getUserID(), user.getCompanyId());
List roleList = user.getRoleList();
for (Role role : roleList) {
authorizationInfo.addRole(role.getRoleName());
if (CommonUtil.check(role.getPowerList())) {
for (Power permission : role.getPowerList()) {
authorizationInfo.addStringPermission(permission.getUrl());
}
}
}
return authorizationInfo;
}
/**
* @param authenticationToken
* @return
* @throws AuthenticationException
* @implNote 身份认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String key = (String) authenticationToken.getPrincipal();
SysUser u = new SysUser();
u.setAccNum(key);
SysUser user = userService.getUserByAcc(u);
if (user == null) {
throw new UnknownAccountException();
} else if ("0".equals(user.getIsLock())) {
throw new LockedAccountException(); // 帐号冻结,非正常
// }
// SysUser admin = userService.getByUId(user.getCreaterId());
// if(admin != null && !"00".equals(admin.getUserState())){
// throw new LockedAccountException(); // 管理员帐号被冻结,非正常
} else {
SimpleAuthenticationInfo simpleAuthenticationInfo =
new SimpleAuthenticationInfo(user, user.getPasswd(), this.getName());
return simpleAuthenticationInfo;
}
}
}
}