jwt与redis,把生成的token放入redis中进行临时存储

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: jwt与redis,把生成的token放入redis中进行临时存储

jwt与redis,把生成的token放入redis中进行临时存储

简介:本文讲解,如何结合jwt与redis,我们把jwt生成的token存放在redis中。

springboot+jwt的教程可以看这篇文章:

vue与jwt验证

SpringBoot+JWT+Shiro

SpringBoot连接redis

讲解

在上面的文章的基础之上,首先是,我们需要加上一些辅助类,依赖还有配置信息。

文章中的代码可以看这里:https://gitee.com/geek-li-hua/code-in-blog.git

  • ErrorCode 统一错误码处理类
public enum  ErrorCode {
    PARAMS_ERROR(10001,"参数有误"),
    ACCOUNT_PWD_NOT_EXIST(10002,"用户名或密码不存在"),
    NO_PERMISSION(70001,"无访问权限"),
    SESSION_TIME_OUT(90001,"会话超时"),
    NO_LOGIN(90002,"未登录"),;
    private int code;
    private String msg;
    ErrorCode(int code, String msg){
        this.code = code;
        this.msg = msg;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
}

依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
</dependency>

配置文件

加上redis的相关配置文件

# Redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=root@123456
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-wait=-1
spring.redis.jedis.pool.max-idle=500
spring.redis.jedis.pool.min-idle=0
spring.redis.lettuce.shutdown-timeout=0

代码

我们需要知道的是,我们生成的token,对于前端,是存储在localstorage里面的,然后对于后端是存储在redis里面的,所以退出只需要删除redis中的存储就可以了。

首先在需要注入redisTemplate。

@Autowired
private RedisTemplate<String, String> redisTemplate;

然后在login中加入下面代码

import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.springbootjwt.Bean.User;
import com.example.springbootjwt.Config.Result;
import com.example.springbootjwt.Dto.LoginDto;
import com.example.springbootjwt.Service.IUserService;
import com.example.springbootjwt.Utils.JWTUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSON;
/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author jakelihua
 * @since 2023-08-14
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private IUserService userService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @PostMapping("/login")
    public Result<Map<String, Object>> login(@RequestBody LoginDto user) {
        // 创建结果对象
        Result<Map<String, Object>> result;
        try {
            // 调用userService的login方法进行用户认证
            User userDB = userService.login(user);
            // 获取用户ID和用户名,并将其放入payload
            Map<String, String> payload = new HashMap<>();
            payload.put("id", userDB.getId().toString());
            payload.put("name", userDB.getUsername());
            // 生成JWT的令牌
            String token = JWTUtils.getToken(payload);
            // 构造成功的结果对象
            result = new Result<>(200, "认证成功");
            result.setData(new HashMap<>());
            result.getData().put("token", token); // 响应token
            redisTemplate.opsForValue().set("TOKEN:" + token, JSON.toJSONString(payload));
        } catch (Exception e) {
            // 构造失败的结果对象
            e.printStackTrace();
            result = Result.fail(500, "账号或密码错误");
        }
        System.out.println(result);
        return result;
    }
    @GetMapping("/index")
    public String index(){
        return "这是主页";
    }
    @PostMapping("/register")
    public Result<Map<String, Object>> register(@RequestBody User user){
        // 创建结果对象
        Result<Map<String, Object>> result;
        User user1 = userService.selectByUsername(user.getUsername());
        if (user1 != null){
            result = Result.fail(405, "用户已存在,请更换用户名");
        } else {
            boolean register = userService.register(user);
            if (register){
                result = new Result(200, "注册成功");
            } else {
                result = Result.fail(500, "注册失败");
            }
        }
        return result;
    }
    @GetMapping("/all/{token}")
    Result<Map<String, Object>> getByAll(@PathVariable String token) {
        List<User> list = userService.list();
        Result<Map<String, Object>> result;
        System.out.println(token);
        try {
            Map<String, Object> map = new HashMap<>();
            // 处理自己的业务逻辑
            // 校验并解析token
            verifyToken(token);
            map.put("data", list);
            // 构造成功的结果对象
            result = new Result<>(200, "请求成功!");
            result.setData(map);
        } catch (Exception e) {
            // 构造失败的结果对象
            result = Result.fail(500, e.getMessage());
        }
        return result;
    }
    private void verifyToken(String token) throws Exception {
        // 校验并解析token
        DecodedJWT verify = JWTUtils.verify(token);
        // 可以在这里添加其他的校验逻辑
        // 打印解析出的用户id和用户名
        log.info("用户id: [{}]", verify.getClaim("id").asString());
        log.info("用户name: [{}]", verify.getClaim("name").asString());
    }
    @GetMapping("/test/{token}")
    public Result<Map<String, Object>> test(@PathVariable String token) {
        // 创建结果对象
        Result<Map<String, Object>> result;
        try {
            Map<String, Object> map = new HashMap<>();
            // 处理自己的业务逻辑
            // 从请求头中获取token
            // 校验并解析token
            DecodedJWT verify = JWTUtils.verify(token);
            // 打印解析出的用户id和用户名
            log.info("用户id: [{}]", verify.getClaim("id").asString());
            log.info("用户name: [{}]", verify.getClaim("name").asString());
            // 构造成功的结果对象
            result = new Result<>(200, "请求成功!");
            result.setData(map);
        } catch (Exception e) {
            // 构造失败的结果对象
            result = Result.fail(500, e.getMessage());
        }
        return result;
    }
}

登录之后,可以看出来,token存储成功了。

  • 对于退出

编写下面这个方法

@GetMapping("/logout/{token}")
    public String logout(@PathVariable String token){
        redisTemplate.opsForValue().getOperations().delete("TOKEN:" + token);
        String value = redisTemplate.opsForValue().get("yourKey");
        System.out.println(value);
        return "退出登录";
    }

  • 对于前端
logout({ commit }) {
      // 清除token并重定向到登录页面
      commit('CLEAR_TOKEN');
      const token = localStorage.getItem('token');
      localStorage.removeItem('token');
      axios.get(`http://localhost:8989/user/logout/${token}`)
      .then(response => {
        console.log("退出成功")
      })
      .catch(error => {
        console.error(error);
      });
      router.push('/');
    },

点击退出之后,就没有了

相关实践学习
基于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天前
|
存储 缓存 NoSQL
深入解析Redis:一种快速、高效的键值存储系统
**Redis** 是一款高性能的键值存储系统,以其内存数据、高效数据结构、持久化机制和丰富的功能在现代应用中占有一席之地。支持字符串、哈希、列表、集合和有序集合等多种数据结构,适用于缓存、计数、分布式锁和消息队列等场景。安装Redis涉及下载、编译和配置`redis.conf`。基本操作包括键值对的设置与获取,以及哈希、列表、集合和有序集合的操作。高级特性涵盖发布/订阅、事务处理和Lua脚本。优化策略包括选择合适数据结构、配置缓存和使用Pipeline。注意安全、监控和备份策略,以确保系统稳定和数据安全。
53 1
|
3月前
|
存储 NoSQL Redis
redis存储原理和数据模型
redis存储原理和数据模型
26 1
|
14天前
|
存储 NoSQL 算法
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)(二)
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)
31 0
|
14天前
|
存储 NoSQL Redis
作者推荐 |【Redis技术进阶之路】「原理系列开篇」揭秘高效存储模型与数据结构底层实现(SDS)(三)
作者推荐 |【Redis技术进阶之路】「原理系列开篇」揭秘高效存储模型与数据结构底层实现(SDS)
17 0
|
2月前
|
存储 缓存 NoSQL
为什么要在 Redis 中存储两次同一份数据?
为什么要在 Redis 中存储两次同一份数据?
37 0
为什么要在 Redis 中存储两次同一份数据?
|
2月前
|
存储 缓存 NoSQL
Redis数据结构的奇妙世界:一窥底层存储机制【redis第一部分】
Redis数据结构的奇妙世界:一窥底层存储机制【redis第一部分】
62 0
|
3月前
|
存储 NoSQL 关系型数据库
Redis Set 用了 2 种数据结构来存储,到现在才知道
Redis Set 用了 2 种数据结构来存储,到现在才知道
36 0
|
3月前
|
存储 NoSQL Redis
Redis(三)存储原理与数据模型(hash冲突、渐进式rehash)
Redis(三)存储原理与数据模型(hash冲突、渐进式rehash)
28 0
|
3月前
|
存储 NoSQL 算法
redis存储什么类型的数据?redis分布式锁怎么实现的?
redis存储什么类型的数据?redis分布式锁怎么实现的?
|
3月前
|
存储 监控 NoSQL
redis7.0源码阅读(二):redis的基本存储结构
redis7.0源码阅读(二):redis的基本存储结构
40 0