Spring Boot + Shiro + Redis 共享 Session 设置失效时间的实现

在现代 web 应用中,安全性和性能是至关重要的。Spring Boot 作为一个流行的框架,结合 Apache Shiro(一个强大的 Java 权限控制框架)和 Redis(一个高性能的键值数据库),可以高效地管理用户会话。这篇文章将探讨如何共享会话以及如何设置会话的失效时间,以确保用户体验与安全性的平衡。

1. 背景知识

在常规的 Web 应用中,用户的登录状态常常使用 Session 来管理。使用 Redis 存储 Session 的一个好处是,它支持高并发和分布式架构。Shiro 插件支持通过 Redis 来管理会话,使得在多个实例之间共享 Session 成为可能。

2. 环境搭建

在开始编写代码之前,确保你已经配置了以下环境:

  • JDK 1.8 或更高版本
  • Spring Boot
  • Redis
  • Maven

你需要在 pom.xml 中添加依赖项:

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-starter</artifactId>
    <version>1.7.0</version> <!-- 版本号根据需要进行调整 -->
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-redis</artifactId>
    <version>2.3.0</version> <!-- 版本号根据需要进行调整 -->
</dependency>

3. 配置 Shiro 和 Redis

application.yml 中,我们需要进行一些基本配置,以确保 Shiro 和 Redis 能正常工作。

shiro:
  redis:
    host: 127.0.0.1
    port: 6379
    timeout: 2000
  session:
    timeout: 3600 # 设置Session过期时间为3600秒

4. 定义 Shiro Configurations

在我们的 Spring Boot 应用中,我们需要创建一个 Shiro 配置类来设置 RedisSessionDAO:

@Configuration
public class ShiroConfig {

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory();
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory());
        return template;
    }

    @Bean
    public SessionDAO sessionDAO() {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisTemplate(redisTemplate());
        return redisSessionDAO;
    }

    @Bean
    public SecurityManager securityManager(SessionDAO sessionDAO) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setSessionDAO(sessionDAO);
        return securityManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        return shiroFilterFactoryBean;
    }
}

5. 实现 Session 失效时间设置

我们可以在 RedisSessionDAO 中进行失效时间的设置。在以下代码示例中,我们演示了如何自定义 Session 过期时间:

public class CustomRedisSessionDAO extends RedisSessionDAO {

    private long timeout = 3600; // 默认3600秒

    // 设置自身失效时间
    public void setTimeout(long timeout) {
        this.timeout = timeout;
    }

    @Override
    protected void doUpdate(Session session) {
        super.doUpdate(session);
        // 更新Session过期时间
        RedisTemplate<String, Serializable> redisTemplate = getRedisTemplate();
        redisTemplate.expire(session.getId().toString(), timeout, TimeUnit.SECONDS);
    }
}

6. 会话流程图

为了更好地理解会话的共享和失效处理,我们可以用以下序列图来表示:

sequenceDiagram
    User->>Web Application: 登录请求
    Web Application->>Shiro: 用户认证
    Shiro->>Redis: 存储会话
    Redis-->>Shiro: 返回会话ID
    Shiro-->>Web Application: 返回登录成功
    Web Application->>Redis: 拉取会话
    Redis-->>Web Application: 返回会话信息
    Web Application->>User: 显示欢迎信息

7. 小结

通过以上步骤,我们成功地在 Spring Boot 中使用 Shiro 和 Redis 实现了共享 Session 的功能,并设置了会话的失效时间。这种设计不仅提高了系统的性能,还增强了系统的可扩展性,对于构建现代 Web 应用而言,具有重要的意义。

使用 Redis 作为持久化的 Session 存储提供了高可用性,而 Shiro 的安全框架使得我们可以在安全性方面得到保障。结合这些技术,可以有效地管理用户的身份和会话状态。

在后续的实践中,你可以根据具体需求对会话的失效策略进行更多调整和优化。希望这篇文章对你有所帮助。如有任何疑问,欢迎讨论!