第一个是继承 AbstractSessionDAO 这个类 这个类是shiro去保存session的
import com.newcoin.manager.web.utils.ShiroSessionRedisManager;
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;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class SessionRedisDao extends AbstractSessionDAO {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private ShiroSessionRedisManager redisManager;
/**
* The Redis key prefix for the sessions
*/
private static final String KEY_PREFIX = "shiro_redis_session:";
@Override
public void update(Session session) throws UnknownSessionException {
this.saveSession(session);
}
@Override
public void delete(Session session) {
if (session == null || session.getId() == null) {
logger.error("session or session id is null");
return;
}
redisManager.del(KEY_PREFIX + session.getId());
}
/*@Override
public Collection<Session> getActiveSessions() {
Set<Session> sessions = new HashSet<Session>();
Set<byte[]> keys = redisManager.keys(KEY_PREFIX + "*");
if(keys != null && keys.size()>0){
for(byte[] key : keys){
String deserialize = SerializerUtil.deserialize(key);
byte[] o = redisManager.get(deserialize);
Session s = (Session) SerializerUtil.deserialize(o);
sessions.add(s);
}
}
return sessions;
}*/
@Override
public Collection<Session> getActiveSessions() {
Set<Session> sessions = new HashSet<Session>();
Set<byte[]> keys = redisManager.keys(KEY_PREFIX + "*");
if(keys != null && keys.size()>0){
for(byte[] key : keys){
// String deserialize = SerializerUtil.deserialize(key);
Session o = redisManager.get(new String(key));
// Session s = (Session) SerializerUtil.deserialize(o.getBytes());
sessions.add(o);
}
}
return sessions;
}
@Override
protected Serializable doCreate(Session session) {
Serializable sessionId = this.generateSessionId(session);
this.assignSessionId(session, sessionId);
this.saveSession(session);
return sessionId;
}
@Override
protected Session doReadSession(Serializable sessionId) {
if(sessionId == null){
logger.error("session id is null");
return null;
}
Session s = (Session)redisManager.get(KEY_PREFIX + sessionId);
return s;
}
private void saveSession(Session session) throws UnknownSessionException {
if (session == null || session.getId() == null) {
logger.error("session or session id is null");
return;
}
//设置过期时间
long expireTime = 1800000l;
session.setTimeout(expireTime);
redisManager.setEx(KEY_PREFIX + session.getId(), session, expireTime);
}
public void setRedisManager(ShiroSessionRedisManager redisManager) {
this.redisManager = redisManager;
}
public ShiroSessionRedisManager getRedisManager() {
return redisManager;
}
}
以下是2个工具类
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
/**
* 序列化工具类
* @author HandyZcy
*
*/
public class SerializerUtil {
private static final JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
/**
* 序列化对象
* @param obj
* @return
*/
public static <T> byte[] serialize(T obj){
try {
return jdkSerializationRedisSerializer.serialize(obj);
} catch (Exception e) {
throw new RuntimeException("序列化失败!", e);
}
}
/**
* 反序列化对象
* @param bytes 字节数组
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T deserialize(byte[] bytes){
try {
return (T) jdkSerializationRedisSerializer.deserialize(bytes);
} catch (Exception e) {
throw new RuntimeException("反序列化失败!", e);
}
}
}
Redis 工具类 具体的RedisTemplate 自己注入
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Set;
@Component
public class ShiroSessionRedisManager {
@Autowired
private RedisTemplate<Object,Object> redisTemplate;
/**
* 过期时间
*/
// private Long expire;
/**
* 添加缓存数据(给定key已存在,进行覆盖)
* @param key
* @param obj
* @throws DataAccessException
*/
public <T> void set(String key, T obj) throws DataAccessException{
final byte[] bkey = key.getBytes();
final byte[] bvalue = SerializerUtil.serialize(obj);
redisTemplate.execute(new RedisCallback<Void>() {
@Override
public Void doInRedis(RedisConnection connection) throws DataAccessException {
connection.set(bkey, bvalue);
return null;
}
});
}
/**
* 添加缓存数据(给定key已存在,不进行覆盖,直接返回false)
* @param key
* @param obj
* @return 操作成功返回true,否则返回false
* @throws DataAccessException
*/
public <T> boolean setNX(String key, T obj) throws DataAccessException{
final byte[] bkey = key.getBytes();
final byte[] bvalue = SerializerUtil.serialize(obj);
boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
return connection.setNX(bkey, bvalue);
}
});
return result;
}
/**
* 添加缓存数据,设定缓存失效时间
* @param key
* @param obj
* @param expireSeconds 过期时间,单位 秒
* @throws DataAccessException
*/
public <T> void setEx(String key, T obj, final long expireSeconds) throws DataAccessException{
final byte[] bkey = key.getBytes();
final byte[] bvalue = SerializerUtil.serialize(obj);
redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
connection.setEx(bkey, expireSeconds, bvalue);
return true;
}
});
}
/**
* 获取key对应value
* @param key
* @return
* @throws DataAccessException
*/
public <T> T get(final String key) throws DataAccessException{
byte[] result = redisTemplate.execute(new RedisCallback<byte[]>() {
@Override
public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
return connection.get(key.getBytes());
}
});
if (result == null) {
return null;
}
return SerializerUtil.deserialize(result);
}
/**
* 删除指定key数据
* @param key
* @return 返回操作影响记录数
*/
public Long del(final String key){
if (StringUtils.isEmpty(key)) {
return 0l;
}
Long delNum = redisTemplate.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {
byte[] keys = key.getBytes();
return connection.del(keys);
}
});
return delNum;
}
public Set<byte[]> keys(final String key){
if (StringUtils.isEmpty(key)) {
return null;
}
Set<byte[]> bytesSet = redisTemplate.execute(new RedisCallback<Set<byte[]>>() {
@Override
public Set<byte[]> doInRedis(RedisConnection connection) throws DataAccessException {
byte[] keys = key.getBytes();
return connection.keys(keys);
}
});
return bytesSet;
}
}
然后再shiro的config那里注入自己写的sessionDao
@Bean
public SessionRedisDao getRedisSessionDao(){
return new SessionRedisDao();
}
@Bean(name="sessionManager")
public DefaultWebSessionManager defaultWebSessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
//sessionManager.setCacheManager(cacheManager());
sessionManager.setGlobalSessionTimeout(43200000); //12小时
sessionManager.setDeleteInvalidSessions(true);
//关键在这里
sessionManager.setSessionDAO(getRedisSessionDao());
sessionManager.setSessionValidationSchedulerEnabled(true);
sessionManager.setDeleteInvalidSessions(true);
sessionManager.setSessionIdCookie(simpleCookie());
// sessionManager.setSessionIdCookie(getSessionIdCookie());
return sessionManager;
}
@Bean(name="securityManager")
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(realm());
// manager.setCacheManager(getRedisManager());
manager.setSessionManager(defaultWebSessionManager());
return manager;
}
//这里是防止shiro的cookie和容器的cookie冲突导致出现刷掉而做
@Bean
public SimpleCookie simpleCookie(){
SimpleCookie simpleCookie = new SimpleCookie();
simpleCookie.setName("shiro.sesssion");
simpleCookie.setPath("/");
return simpleCookie;
}
万事大吉
然后在登陆那边 去进行排挤的代码 贴一下
Collection<Session> sessions = sessionRedisDao.getActiveSessions();
String principalsSessionValue = null;
for (Session session : sessions) {
Object attribute = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
principalsSessionValue = attribute==null?null:attribute.toString();
if(StringUtils.equals(userVo.getAccount(), principalsSessionValue)){
// session.setTimeout(0); //这里就把session清除
sessionRedisDao.delete(session); //session清除,
}
}