基于 Shiro 和 Redis 的多机单点登录系统

在微服务架构不断推广的今天,单点登录(SSO)成为了解决多个系统之间认证问题的重要方式。本文将介绍如何通过 Apache Shiro 和 Redis 实现一个多机单点登录的系统。

什么是单点登录?

单点登录是一种用户身份认证的解决方案,用户只需在一个位置登录即可访问多个应用系统,而不需要在每个系统中重复登录。这样不但提升了用户体验,也降低了因为密码存储在多个地方而带来的安全风险。

Shiro 和 Redis 介绍

  • Apache Shiro:一个强大且灵活的 Java 安全框架,支持身份验证、授权、会话管理和加密等功能。
  • Redis:一个开源的高性能键值对存储数据库,支持数据持久化,可用作缓存和消息代理。

多机单点登录的原理

在多机单点登录中,用户的会话信息需要在多个应用之间保持同步。这里我们利用 Redis 的分布式特性来存储和管理用户的会话信息。当用户在一个应用成功登录后,系统会将用户的会话信息存储到 Redis 中,其他应用可以通过 Redis 访问这些信息,从而实现单点登录。

系统架构图

pie
    title 单点登录架构图
    "用户": 40
    "应用A": 30
    "应用B": 30

开发步骤

1. 引入依赖

首先,在 Java Maven 项目中引入 Shiro 和 Redis 的相关依赖。

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.8.0</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.8.0</version>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.6.3</version>
</dependency>

2. 配置 Shiro

在 Shiro 的配置文件中,定义 Realm、SessionManager 和 CacheManager 使用 Redis。在 shiro.ini 文件中进行以下配置:

[main]
redisManager = redis.clients.jedis.JedisPool("127.0.0.1", 6379)
redisCacheManager = org.apache.shiro.cache.redis.RedisCacheManager
redisCacheManager.redisManager = $redisManager

shiro.sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
shiro.sessionManager.cacheManager = $redisCacheManager
shiro.sessionManager.globalSessionTimeout = 3600000  # 1小时

3. 处理用户登录

在用户登录时,需要将用户会话信息存储到 Redis 中。如果登录成功,将用户的信息存入 Redis:

public void login(String username, String password) {
    Subject currentUser = SecurityUtils.getSubject();
    
    UsernamePasswordToken token = new UsernamePasswordToken(username, password);
    currentUser.login(token);
    
    // 存储会话信息到 Redis
    String sessionId = (String) currentUser.getSession().getId();
    redisTemplate.opsForValue().set(sessionId, username);
}

4. 实现注销

用户注销时,需要清除 Redis 中的用户会话信息:

public void logout() {
    Subject currentUser = SecurityUtils.getSubject();
    
    // 清除 Redis 中的会话信息
    String sessionId = (String) currentUser.getSession().getId();
    redisTemplate.delete(sessionId);
    
    currentUser.logout();
}

5. 其他应用的登录校验

当其他应用接收到请求时,可以通过用户提供的 Session ID 从 Redis 中获取用户信息并进行验证。

public boolean validateSession(String sessionId) {
    String username = redisTemplate.opsForValue().get(sessionId);
    return username != null;
}

总结

通过以上步骤,我们利用 Apache Shiro 和 Redis 实现了一个多机单点登录的系统。这种架构不仅提升了用户体验,还增强了安全性。未来可以根据业务需求,继续扩展系统的功能和性能。希望这篇文章能为你提供启发,让你在项目中顺利实现单点登录功能。