jwt与redis,把生成的token放入redis中进行临时存储
简介:本文讲解,如何结合jwt与redis,我们把jwt生成的token存放在redis中。
springboot+jwt的教程可以看这篇文章:
vue与jwt验证
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('/');
},
点击退出之后,就没有了