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

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容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
相关文章
|
8天前
|
安全 Java Apache
SpringBoot+Shiro(一)
SpringBoot+Shiro(一)
|
6天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的大学竞赛报名管理系统
基于Java+Springboot+Vue开发的大学竞赛报名管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的大学竞赛报名管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
20 3
基于Java+Springboot+Vue开发的大学竞赛报名管理系统
|
7天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的蛋糕商城管理系统
基于Java+Springboot+Vue开发的蛋糕商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的蛋糕商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
20 3
基于Java+Springboot+Vue开发的蛋糕商城管理系统
|
7天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的美容预约管理系统
基于Java+Springboot+Vue开发的美容预约管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的美容预约管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
21 3
基于Java+Springboot+Vue开发的美容预约管理系统
|
9天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的房产销售管理系统
基于Java+Springboot+Vue开发的房产销售管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的房产销售管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
23 3
基于Java+Springboot+Vue开发的房产销售管理系统
|
6天前
|
JSON NoSQL Java
redis的java客户端的使用(Jedis、SpringDataRedis、SpringBoot整合redis、redisTemplate序列化及stringRedisTemplate序列化)
这篇文章介绍了在Java中使用Redis客户端的几种方法,包括Jedis、SpringDataRedis和SpringBoot整合Redis的操作。文章详细解释了Jedis的基本使用步骤,Jedis连接池的创建和使用,以及在SpringBoot项目中如何配置和使用RedisTemplate和StringRedisTemplate。此外,还探讨了RedisTemplate序列化的两种实践方案,包括默认的JDK序列化和自定义的JSON序列化,以及StringRedisTemplate的使用,它要求键和值都必须是String类型。
redis的java客户端的使用(Jedis、SpringDataRedis、SpringBoot整合redis、redisTemplate序列化及stringRedisTemplate序列化)
|
Java 数据库 数据安全/隐私保护
Java秒杀系统实战系列~整合Shiro实现用户登录认证
本篇博文是“Java秒杀系统实战系列文章”的第五篇,在本篇博文中,我们将整合权限认证-授权框架Shiro,实现用户的登陆认证功能,主要用于:要求用户在抢购商品或者秒杀商品时,限制用户进行登陆!并对于特定的url(比如抢购请求对应的url)进行过滤(即当用户访问指定的url时,需要要求用户进行登陆)。
3831 0
|
5天前
|
安全 Java 调度
Java编程时多线程操作单核服务器可以不加锁吗?
Java编程时多线程操作单核服务器可以不加锁吗?
18 2
|
9天前
|
存储 缓存 Java
java线程内存模型底层实现原理
java线程内存模型底层实现原理
java线程内存模型底层实现原理
|
13天前
|
缓存 Java 应用服务中间件
Java虚拟线程探究与性能解析
本文主要介绍了阿里云在Java-虚拟-线程任务中的新进展和技术细节。
下一篇
无影云桌面