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

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
全局流量管理 GTM,标准版 1个月
简介: 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
相关文章
|
3月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(一)
数据的存储--Redis缓存存储(一)
117 1
|
3月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(二)
数据的存储--Redis缓存存储(二)
54 2
数据的存储--Redis缓存存储(二)
|
3月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
85 6
|
5月前
|
存储 缓存 NoSQL
【Azure Redis 缓存】关于Azure Cache for Redis 服务在传输和存储键值对(Key/Value)的加密问题
【Azure Redis 缓存】关于Azure Cache for Redis 服务在传输和存储键值对(Key/Value)的加密问题
|
18天前
|
存储 消息中间件 监控
Redis Stream:实时数据流的处理与存储
通过上述分析和具体操作示例,您可以更好地理解和应用 Redis Stream,满足各种实时数据处理需求。
53 14
|
2月前
|
存储 NoSQL 算法
Redis分片集群中数据是怎么存储和读取的 ?
Redis集群采用哈希槽分区算法,共有16384个哈希槽,每个槽分配到不同的Redis节点上。数据操作时,通过CRC16算法对key计算并取模,确定其所属的槽和对应的节点,从而实现高效的数据存取。
56 13
|
2月前
|
JSON 安全 Go
Go语言中使用JWT鉴权、Token刷新完整示例,拿去直接用!
本文介绍了如何在 Go 语言中使用 Gin 框架实现 JWT 用户认证和安全保护。JWT(JSON Web Token)是一种轻量、高效的认证与授权解决方案,特别适合微服务架构。文章详细讲解了 JWT 的基本概念、结构以及如何在 Gin 中生成、解析和刷新 JWT。通过示例代码,展示了如何在实际项目中应用 JWT,确保用户身份验证和数据安全。完整代码可在 GitHub 仓库中查看。
267 1
|
2月前
|
存储 NoSQL Redis
【赵渝强老师】Redis的存储结构
Redis 默认配置包含 16 个数据库,通过 `databases` 参数设置。每个数据库编号从 0 开始,默认连接 0 号数据库,可通过 `SELECT &lt;dbid&gt;` 切换。Redis 的核心存储结构包括 `dict`、`expires` 等字段,用于处理键值和过期行为。添加键时需指定数据库信息。视频讲解和代码示例详见内容。
|
4月前
|
存储 中间件 API
ThinkPHP 集成 jwt 技术 token 验证
本文介绍了在ThinkPHP框架中集成JWT技术进行token验证的流程,包括安装JWT扩展、创建Token服务类、编写中间件进行Token校验、配置路由中间件以及测试Token验证的步骤和代码示例。
ThinkPHP 集成 jwt 技术 token 验证
|
3月前
|
JSON NoSQL Java
springBoot:jwt&redis&文件操作&常见请求错误代码&参数注解 (九)
该文档涵盖JWT(JSON Web Token)的组成、依赖、工具类创建及拦截器配置,并介绍了Redis的依赖配置与文件操作相关功能,包括文件上传、下载、删除及批量删除的方法。同时,文档还列举了常见的HTTP请求错误代码及其含义,并详细解释了@RequestParam与@PathVariable等参数注解的区别与用法。