此图非常重要!!!镇楼
0x001 重写SessionManager
shiro提供了三种默认实现:
- DefaultSessionManager: 用于java se 环境
- ServletContainerSessionManager:默认使用的实现,Servlet容器管理
- DefaultWebSessionManager:自己维护
重写SessionManager
需要继承DefaultWebSessionManager
类
目的:自定义从header
中的Authorization
获取token
public class CustomSessionManager extends DefaultWebSessionManager {
@Override
protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
String id = WebUtils.toHttp(request).getHeader("Authorization");
if (StringUtils.isEmpty(id)) {
// 获取sessionId,id可以自定义
return super.getSessionId(request, response);
} else {
//返回sessionId;固定套路
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, "header");
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
return id;
}
}
}
0x002 重写SessionDao
重写SessionDao
需要实现SessionDAO
接口
继承以下子类也可以:
继承AbstractSessionDAO
,其实现了基础的实现
ps:
注意!!!!!!!
扫描二维码关注公众号,回复:
9303871 查看本文章
一定要自己把session转换成二进制在用redistemplate存到redis 中,直接用redistemplate的对象序列化器,会出错误!!!!!
@Component
public class SelfSessionDao extends AbstractSessionDAO {
@Resource(name = "SessionRedisTemplate")
private RedisTemplate<Object, byte[]> redisTemplate;
// 创建session 存到redis
@Override
protected Serializable doCreate(Session session) {
Serializable sessionId = generateSessionId(session);
assignSessionId(session, sessionId);
redisTemplate.boundValueOps(AppConstants.SHIRO_SESSION_REDIS_PREFIX + sessionId)
.set(sessionToByte(session), AppConstants.TOKEN_EXPIRES_HOUR, TimeUnit.HOURS);
return sessionId;
}
@Override
protected Session doReadSession(Serializable sessionId) {
byte[] bytes = redisTemplate.boundValueOps(AppConstants.SHIRO_SESSION_REDIS_PREFIX + sessionId).get();
return byteToSession(bytes);
}
/**
* 更新
* @param session
* @throws UnknownSessionException
*/
@Override
public void update(Session session) throws UnknownSessionException {
if (session == null || session.getId() == null) {
throw new UnknownSessionException("session 或者 sessionId为空");
}
redisTemplate.boundValueOps(AppConstants.SHIRO_SESSION_REDIS_PREFIX + session.getId())
.set(sessionToByte(session), AppConstants.TOKEN_EXPIRES_HOUR, TimeUnit.HOURS);
}
/**
* 删除session
* @param session
*/
@Override
public void delete(Session session) {
redisTemplate.delete(AppConstants.SHIRO_SESSION_REDIS_PREFIX + session.getId());
}
@Override
public Collection<Session> getActiveSessions() {
Set<Object> keys = redisTemplate.keys(AppConstants.SHIRO_SESSION_REDIS_PREFIX + "*");
if (keys != null) {
return keys.stream().map(key -> {
byte[] bytes = redisTemplate.boundValueOps(key).get();
return byteToSession(bytes);
}).collect(Collectors.toList());
} else {
return null;
}
}
// 把session对象转化为byte保存到redis中
public byte[] sessionToByte(Session session){
ByteArrayOutputStream bo = new ByteArrayOutputStream();
byte[] bytes = null;
try {
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(session);
bytes = bo.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return bytes;
}
// 把byte还原为session
public Session byteToSession(byte[] bytes){
ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
ObjectInputStream in;
SimpleSession session = null;
try {
in = new ObjectInputStream(bi);
session = (SimpleSession) in.readObject();
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
return session;
}
}
0x003自定义id生成器
public class CustomSessionIdGenerator implements SessionIdGenerator {
@Override
public Serializable generateId(Session session) {
//... 生成id逻辑
return id;
}
}
0x004 配置类
@Bean
public SecurityManager getSecurityManager(CustomRealm realm,DefaultWebSessionManager defaultWebSessionManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm);
//将自定义的会话管理器注册到安全管理器中
securityManager.setSessionManager(defaultWebSessionManager);
//将自定义的redis缓存管理器注册到安全管理器中
securityManager.setCacheManager(selfCacheManager());
return securityManager;
}
//会话管理器
@Bean
public DefaultWebSessionManager sessionManager(SelfSessionDao selfSessionDao) {
CustomSessionManager sessionManager = new CustomSessionManager();
// 自定义sessionDAO
sessionManager.setSessionDAO(selfSessionDao);
// 自定义id生成器
selfSessionDao.setSessionIdGenerator(new CustomSessionIdGenerator());
return sessionManager;
}