在查看相关redis方法实现session共享时,其实只需要替换sessionDao就可以实现。不用实现redisManage。
具体代码如下:RedisSessionDao.class
package com.fg.car.backweb.shiro;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
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 org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;
import com.fg.car.framework.config.RedisObjectSerializer;
/**
* *********************************************
* @ClassName: RedisSessionDao
* @Description:TODO(这里用一句话描述这个类的作用)
* @Author ganjing
* @Date 2018年11月14日
* @Copyright: 2018 天誉飞歌(重庆)研究院版权所有
**********************************************
*/
@Configuration
@Service
public class RedisSessionDao extends AbstractSessionDAO {
private static Logger logger = LoggerFactory.getLogger(RedisSessionDao.class);
@Autowired
private RedisTemplate<String, Object> template;
private String keyPrefix = "shiro-session:";
private String getKey(String key) {
return keyPrefix+key;
}
/**
* **************************************************
* @Title: update
* @Description: 修改session
* @Param:@param session
* @Param:@throws UnknownSessionException
* @see org.apache.shiro.session.mgt.eis.SessionDAO#update(org.apache.shiro.session.Session)
****************************************************
*/
@Override
public void update(Session session) throws UnknownSessionException {
logger.debug("更新seesion,id=[{}]", session.getId().toString());
try {
getRedisTemplate().opsForValue().set(getKey(session.getId().toString()),session,30,TimeUnit.MINUTES);
} catch (Exception e) {
logger.error(e.getMessage(),e);
}
}
@Override
public void delete(Session session) {
logger.debug("删除seesion,id=[{}]", session.getId().toString());
try {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
String key=getKey(session.getId().toString());
redisTemplate.delete(key);
} catch (Exception e) {
logger.error(e.getMessage(),e);
}
}
@Override
public Collection<Session> getActiveSessions() {
logger.info("获取存活的session");
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
Set<Session> sessions = new HashSet<>();
Set<String> keys = redisTemplate.keys(getKey("*"));
if (keys != null && keys.size() > 0) {
for (String key : keys) {
Session s = (Session) redisTemplate.opsForValue().get(key);
sessions.add(s);
}
}
return sessions;
}
@SuppressWarnings("rawtypes")
@Override
protected Serializable doCreate(Session session) {
Serializable sessionId = generateSessionId(session);
assignSessionId(session, sessionId);
logger.debug("创建seesion,id=[{}]", session.getId().toString());
try {
getRedisTemplate().opsForValue().set(sessionId.toString(),session);
} catch (Exception e) {
e.printStackTrace();
logger.error(e.getMessage(),e);
}
return sessionId;
}
@SuppressWarnings("rawtypes")
@Override
protected Session doReadSession(Serializable sessionId) {
logger.debug("获取seesion,id=[{}]", sessionId.toString());
Session readSession = null;
try {
Object obj = getRedisTemplate().opsForValue().get(sessionId.toString());
readSession = (Session)obj;
} catch (Exception e) {
e.printStackTrace();
logger.error(e.getMessage());
}
return readSession;
}
public RedisTemplate<String, Object> getRedisTemplate(){
RedisTemplate<String, Object> template1 = new RedisTemplate<String, Object>();
template1.setConnectionFactory(template.getConnectionFactory());
template1.setKeySerializer(new StringRedisSerializer());
template1.setValueSerializer(new RedisObjectSerializer());
template1.afterPropertiesSet();
return template1;
}
}
注意:session序列化时只能自己实现RedisObjectSerializer的,不能使用Jackson2JsonRedisSerializer。会保存。
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.Filter;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
import com.fg.car.backweb.shiro.OAuth2Filter;
import com.fg.car.backweb.shiro.OAuth2Realm;
import com.fg.car.backweb.shiro.RedisSessionDao;
import com.fg.car.backweb.shiro.ShiroLifecycleBeanPostProcessorConfig;
ShiroConfig.class
/**
* *********************************************
* @ClassName: ShiroConfig
* @Description:shiro配置
* @Author ganjing
* @Date 2018年11月5日
* @Copyright: 2018 天誉飞歌(重庆)研究院版权所有
**********************************************
*/
@Configuration
@AutoConfigureAfter(ShiroLifecycleBeanPostProcessorConfig.class)
@Service
public class ShiroConfig {
@Autowired
private RedisSessionDao redisSessionDao;
private static final String NAME = "custom.name";
private static final String VALUE = "/";
@Bean
public DefaultWebSessionManager sessionManager(RedisSessionDao sessionDAO, SimpleCookie simpleCookie) {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionDAO(redisSessionDao);
sessionManager.setSessionIdCookieEnabled(true);
sessionManager.setSessionIdCookie(simpleCookie);
return sessionManager;
}
@Bean
public SimpleCookie simpleCookie() {
SimpleCookie simpleCookie = new SimpleCookie();
simpleCookie.setName(NAME);
simpleCookie.setValue(VALUE);
return simpleCookie;
}
@Bean("securityManager")
public SecurityManager securityManager(OAuth2Realm oAuth2Realm, SessionManager sessionManager) {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setSessionManager(sessionManager);
//manager.setCacheManager(redisCacheManager);
manager.setRealm(oAuth2Realm);
return manager;
}
@Bean("shiroFilter")
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager);
//oauth过滤
Map<String, Filter> filters = new HashMap<>();
filters.put("oauth2", new OAuth2Filter());
shiroFilter.setFilters(filters);
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/webjars/**", "anon");
filterMap.put("/druid/**", "anon");
filterMap.put("/app/**", "anon");
filterMap.put("/login", "anon");
filterMap.put("/swagger/**", "anon");
filterMap.put("/v2/api-docs", "anon");
filterMap.put("/swagger-ui.html", "anon");
filterMap.put("/swagger-resources/**", "anon");
filterMap.put("/captcha.jpg", "anon");
filterMap.put("/**", "oauth2");
shiroFilter.setFilterChainDefinitionMap(filterMap);
return shiroFilter;
}
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
proxyCreator.setProxyTargetClass(true);
return proxyCreator;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
}
ShiroLifecycleBeanPostProcessorConfig类
@Configuration
public class ShiroLifecycleBeanPostProcessorConfig {
/**
* Shiro生命周期处理器
*
* @return
*/
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
}
注意上面标注为红色的地方只能单独写一个类。不能放到shiroConfig里面,不然@Bean无法注入。
package com.fg.car.framework.config;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
RedisObjectSerializer类
/**
* *********************************************
* @ClassName: RedisObjectSerializer
* @Description:redis序列化对象
* @Author ganjing
* @Date 2018年11月14日
* @Copyright: 2018 天誉飞歌(重庆)研究院版权所有
**********************************************
*/
public class RedisObjectSerializer implements RedisSerializer<Object> {
private Converter<Object, byte[]> serializer = new SerializingConverter();
private Converter<byte[], Object> deserializer = new DeserializingConverter();
static final byte[] EMPTY_ARRAY = new byte[0];
public Object deserialize(byte[] bytes) {
if (isEmpty(bytes)) {
return null;
}
try {
return deserializer.convert(bytes);
} catch (Exception ex) {
throw new SerializationException("Cannot deserialize", ex);
}
}
public byte[] serialize(Object object) {
if (object == null) {
return EMPTY_ARRAY;
}
try {
return serializer.convert(object);
} catch (Exception ex) {
return EMPTY_ARRAY;
}
}
private boolean isEmpty(byte[] data) {
return (data == null || data.length == 0);
}
}