Shiro + Redis自定义session会话管理

Shiro + Redis自定义session会话管理

博客:Shiro + Redis自定义session会话管理
此图非常重要!!!镇楼

Shiro + Redis自定义session会话管理_第1张图片

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,其实现了基础的实现

@Component
public class SelfSessionDao extends AbstractSessionDAO {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    private final String prefix = "shiro:session";
    // 创建session,保存到数据库
    @Override
    protected Serializable doCreate(Session session) {
        Serializable sessionId = generateSessionId(session);

        String s = JSON.toJSONString(session);
        System.out.println("doCreate:" + s);
        // 必须要将生成的id设置到session实力当中
        assignSessionId(session,sessionId);
        redisTemplate.boundValueOps(prefix + sessionId).set(session);
        return sessionId;
    }

    @Override
    protected Session doReadSession(Serializable sessionId) {
        return (Session) redisTemplate.boundValueOps(prefix + sessionId).get();
    }

    @Override
    public void update(Session session) throws UnknownSessionException {
        if (session == null || session.getId() == null) {
            throw new UnknownSessionException("session 或者 session为空");
        }
        redisTemplate.boundValueOps(prefix + session.getId()).set(session);
    }

    @Override
    public void delete(Session session) {
        redisTemplate.delete(prefix + session.getId());
    }

    @Override
    public Collection<Session> getActiveSessions() {
        Set<Object> keys = redisTemplate.keys(prefix);

        if (keys != null) {
            return keys.stream().map(key -> {
                Session s = (Session) redisTemplate.boundValueOps(key).get();
                return s;
            }).collect(Collectors.toList());

        } else {
            return null;
        }
    }
}

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;
    }

你可能感兴趣的:(shiro,shiro,session,redis)