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

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
云数据库 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);
    }
}
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
4天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
|
1天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的音乐推荐管理系统
基于Java+Springboot+Vue开发的音乐推荐管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的音乐推荐管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
30 8
基于Java+Springboot+Vue开发的音乐推荐管理系统
|
1天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的母婴商城管理系统
基于Java+Springboot+Vue开发的母婴商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的网上母婴商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
18 7
基于Java+Springboot+Vue开发的母婴商城管理系统
|
2天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的在线摄影预约管理系统
基于Java+Springboot+Vue开发的在线摄影预约管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的在线摄影管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
17 8
基于Java+Springboot+Vue开发的在线摄影预约管理系统
|
2天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的农产品商城管理系统
基于Java+Springboot+Vue开发的农产品商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。 通过学习基于Java的农产品商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
15 5
基于Java+Springboot+Vue开发的农产品商城管理系统
|
2天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的新闻管理系统
基于Java+Springboot+Vue开发的新闻管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的新闻管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
14 3
基于Java+Springboot+Vue开发的新闻管理系统
|
3天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的旅游景区管理系统
基于Java+Springboot+Vue开发的旅游景区管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的旅游景区管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
17 4
基于Java+Springboot+Vue开发的旅游景区管理系统
|
3天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的体育用品商城管理系统
基于Java+Springboot+Vue开发的体育用品商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的体育用品商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
14 2
基于Java+Springboot+Vue开发的体育用品商城管理系统
|
3天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的体育场馆预约管理系统
基于Java+Springboot+Vue开发的体育场馆预约管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的体育场馆管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
12 2
基于Java+Springboot+Vue开发的体育场馆预约管理系统
|
5天前
|
存储 缓存 NoSQL
【Java面试题汇总】Redis篇(2023版)
Redis的数据类型、zset底层实现、持久化策略、分布式锁、缓存穿透、击穿、雪崩的区别、双写一致性、主从同步机制、单线程架构、高可用、缓存淘汰策略、Redis事务是否满足ACID、如何排查Redis中的慢查询
【Java面试题汇总】Redis篇(2023版)