Java Spring Boot中使用Shiro、JWT和Redis实现用户登录鉴权

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: Java Spring Boot中使用Shiro、JWT和Redis实现用户登录鉴权
  1. 引入依赖: 添加Shiro、JWT和Redis的依赖项。
  2. 配置Shiro: 配置Shiro的安全管理器、Realm等。
  3. 实现JWT工具类: 生成JWT Token、验证Token等功能。
  4. Controller层: 实现登录接口和受保护资源的访问接口。

首先,确保在pom.xml文件中添加以下依赖:

<!-- Shiro -->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-starter</artifactId>
    <version>1.8.0</version> <!-- 替换为最新版本 -->
</dependency>
 
<!-- JWT -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version> <!-- 替换为最新版本 -->
</dependency>
 
<!-- Redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

接下来,我们按照步骤逐步实现。

1. 配置Shiro

在Spring Boot的配置类中配置Shiro,主要是配置安全管理器、Realm等。

@Configuration
public class ShiroConfig {
 
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);
        shiroFilter.setLoginUrl("/login"); // 登录URL
 
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 配置不需要权限认证的路径,比如登录接口
        filterChainDefinitionMap.put("/login", "anon");
        // 其他路径都需要认证
        filterChainDefinitionMap.put("/**", "authc");
 
        shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilter;
    }
 
    @Bean
    public SecurityManager securityManager(UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        return securityManager;
    }
 
    @Bean
    public UserRealm userRealm() {
        return new UserRealm();
    }
 
    // 注册ShiroDialect,用于Thymeleaf中使用Shiro标签
    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }
}

2. 实现JWT工具类

编写JWT工具类来生成Token、验证Token,并结合Redis进行存储管理。

@Component
public class JwtUtil {
 
    @Value("${jwt.secret}")
    private String secret;
 
    @Value("${jwt.expiration}")
    private long expiration;
 
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
 
    // 生成Token
    public String generateToken(String username) {
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + expiration);
 
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(now)
                .setExpiration(expiryDate)
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }
 
    // 从Token中获取用户名
    public String getUsernameFromToken(String token) {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody()
                .getSubject();
    }
 
    // 验证Token是否有效
    public boolean validateToken(String token, UserDetails userDetails) {
        String username = getUsernameFromToken(token);
        return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
    }
 
    // Token是否过期
    public boolean isTokenExpired(String token) {
        Date expiration = Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody()
                .getExpiration();
        return expiration.before(new Date());
    }
 
    // 保存Token到Redis
    public void saveTokenToRedis(String username, String token) {
        redisTemplate.opsForValue().set(username, token, expiration, TimeUnit.MILLISECONDS);
    }
 
    // 从Redis中删除Token
    public void deleteTokenFromRedis(String username) {
        redisTemplate.delete(username);
    }
 
    // 从Redis中获取Token
    public String getTokenFromRedis(String username) {
        return redisTemplate.opsForValue().get(username);
    }
}

3. Controller层

实现登录接口和需要认证的资源接口。

@RestController
public class AuthController {
 
    @Autowired
    private JwtUtil jwtUtil;
 
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
 
    @PostMapping("/login")
    public ResponseEntity<String> login(@RequestParam String username, @RequestParam String password) {
        // TODO: 根据用户名和密码验证用户身份,省略具体实现
 
        // 假设验证通过,生成Token并保存到Redis
        String token = jwtUtil.generateToken(username);
        jwtUtil.saveTokenToRedis(username, token);
 
        return ResponseEntity.ok(token);
    }
 
    @GetMapping("/protected/resource")
    public ResponseEntity<String> protectedResource(@RequestHeader("Authorization") String authorizationHeader) {
        String token = authorizationHeader.substring(7); // 去除Bearer
 
        // 验证Token是否有效,并从Token中获取用户名
        String username = jwtUtil.getUsernameFromToken(token);
 
        // TODO: 根据用户名获取受保护资源,省略具体实现
 
        return ResponseEntity.ok("Protected resource accessed by " + username);
    }
}
相关文章
|
5月前
|
安全 Java 数据库
第16课:Spring Boot中集成 Shiro
第16课:Spring Boot中集成 Shiro
797 0
|
2月前
|
NoSQL Java 网络安全
SpringBoot启动时连接Redis报错:ERR This instance has cluster support disabled - 如何解决?
通过以上步骤一般可以解决由于配置不匹配造成的连接错误。在调试问题时,一定要确保服务端和客户端的Redis配置保持同步一致。这能够确保SpringBoot应用顺利连接到正确配置的Redis服务,无论是单机模式还是集群模式。
250 5
|
3月前
|
存储 SQL NoSQL
Redis-常用语法以及java互联实践案例
本文详细介绍了Redis的数据结构、常用命令及其Java客户端的使用,涵盖String、Hash、List、Set、SortedSet等数据类型及操作,同时提供了Jedis和Spring Boot Data Redis的实战示例,帮助开发者快速掌握Redis在实际项目中的应用。
312 1
Redis-常用语法以及java互联实践案例
|
3月前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
242 0
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
6月前
|
缓存 监控 NoSQL
Redis 实操要点:Java 最新技术栈的实战解析
本文介绍了基于Spring Boot 3、Redis 7和Lettuce客户端的Redis高级应用实践。内容包括:1)现代Java项目集成Redis的配置方法;2)使用Redisson实现分布式可重入锁与公平锁;3)缓存模式解决方案,包括布隆过滤器防穿透和随机过期时间防雪崩;4)Redis数据结构的高级应用,如HyperLogLog统计UV和GeoHash处理地理位置。文章提供了详细的代码示例,涵盖Redis在分布式系统中的核心应用场景,特别适合需要处理高并发、分布式锁等问题的开发场景。
427 41
|
5月前
|
Java 数据库连接 API
Java 8 + 特性及 Spring Boot 与 Hibernate 等最新技术的实操内容详解
本内容涵盖Java 8+核心语法、Spring Boot与Hibernate实操,按考试考点分类整理,含技术详解与代码示例,助力掌握最新Java技术与应用。
174 2
|
6月前
|
缓存 NoSQL Java
Java Redis 面试题集锦 常见高频面试题目及解析
本文总结了Redis在Java中的核心面试题,包括数据类型操作、单线程高性能原理、键过期策略及分布式锁实现等关键内容。通过Jedis代码示例展示了String、List等数据类型的操作方法,讲解了惰性删除和定期删除相结合的过期策略,并提供了Spring Boot配置Redis过期时间的方案。文章还探讨了缓存穿透、雪崩等问题解决方案,以及基于Redis的分布式锁实现,帮助开发者全面掌握Redis在Java应用中的实践要点。
362 6
|
6月前
|
Java 数据库连接 API
Java 对象模型现代化实践 基于 Spring Boot 与 MyBatis Plus 的实现方案深度解析
本文介绍了基于Spring Boot与MyBatis-Plus的Java对象模型现代化实践方案。采用Spring Boot 3.1.2作为基础框架,结合MyBatis-Plus 3.5.3.1进行数据访问层实现,使用Lombok简化PO对象,MapStruct处理对象转换。文章详细讲解了数据库设计、PO对象实现、DAO层构建、业务逻辑封装以及DTO/VO转换等核心环节,提供了一个完整的现代化Java对象模型实现案例。通过分层设计和对象转换,实现了业务逻辑与数据访问的解耦,提高了代码的可维护性和扩展性。
249 1
|
6月前
|
Java 调度 流计算
基于Java 17 + Spring Boot 3.2 + Flink 1.18的智慧实验室管理系统核心代码
这是一套基于Java 17、Spring Boot 3.2和Flink 1.18开发的智慧实验室管理系统核心代码。系统涵盖多协议设备接入(支持OPC UA、MQTT等12种工业协议)、实时异常检测(Flink流处理引擎实现设备状态监控)、强化学习调度(Q-Learning算法优化资源分配)、三维可视化(JavaFX与WebGL渲染实验室空间)、微服务架构(Spring Cloud构建分布式体系)及数据湖建设(Spark构建实验室数据仓库)。实际应用中,该系统显著提升了设备调度效率(响应时间从46分钟降至9秒)、设备利用率(从41%提升至89%),并大幅减少实验准备时间和维护成本。
358 0
|
JSON 算法 安全
SpringBoot从入门到精通(三十四)如何集成JWT实现Token验证
近年来,随着前后端分离、微服务等架构的兴起,传统的cookie+session身份验证模式已经逐渐被基于Token的身份验证模式取代。接下来介绍如何在Spring Boot项目中集成JWT实现Token验证。
SpringBoot从入门到精通(三十四)如何集成JWT实现Token验证