jwt与redis,把生成的token放入redis中进行临时存储
简介:本文讲解,如何结合jwt与redis,我们把jwt生成的token存放在redis中。
springboot+jwt的教程可以看这篇文章:
讲解
在上面的文章的基础之上,首先是,我们需要加上一些辅助类,依赖还有配置信息。
文章中的代码可以看这里: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('/'); },
点击退出之后,就没有了