序:如何保存用户的登录状态?可能你会说用Session,对于使用Session这个解决办法,我会给出good but wrong
传统的Session登录认证:用户登录时,向服务器发送两次请求,我们在服务器存储用户登录信息,且会在浏览器存储一份cookie。之后浏览器在发送请求时,就会携带cookie,服务器根据cookie中携带的SessionId查找对应的Session,来判断用户是否登录。
这块详细可查看该文
JWT:它将用户信息加密到Token中,服务器并不保存用户信息,服务器只需要根据保存的密钥验证token是否正确以判断是否登录成功
JWT由三部分构成:第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature)
- POM.xml中添加依赖
<!-- jwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 控制层登录逻辑
简单地将参数传给Service,交由Service层处理
@PostMapping
public Result login(@RequestBody LoginParam loginParam){
return loginService.login(loginParam);
}
-
Service层处理逻辑
采用接口分离的模式去处理Service层,编写一个实现类//1.检查参数是否合法 //2.根据用户名和密码去user表中查询 是否存在 //3.如果不存在 登录失败 //4. 如果存在 使用jwt 生成token 返回给前端 //5. token放入redis token:user信息 设置过期时间(登录认证的时候 先认证token字符串是否合法 ,去redis认证是否存在)
public Result login(LoginParam loginParam) {
String account= loginParam.getAccount();
String password = loginParam.getPassword();
if (StringUtils.isBlank(account) || StringUtils.isBlank(password)){
return Result.fail(ErrorCode.PARAMS_ERROR.getCode(),ErrorCode.PARAMS_ERROR.getMsg());
}
password = DigestUtils.md5Hex(password+slat);
SysUser sysUser = sysUserService.findUser(account,password);
if (sysUser == null){
return Result.fail(ErrorCode.ACCOUNT_PWD_NOT_EXIST.getCode(),ErrorCode.ACCOUNT_PWD_NOT_EXIST.getMsg());
}
String token = JWTUtils.createToken(sysUser.getId());
redisTemplate.opsForValue().set("TOKEN_"+token, JSON.toJSONString(sysUser),1, TimeUnit.DAYS);
return Result.success(token);
}
登录的关键在于token,如果退出业务,我们直接删除token
@Override
public Result logout(String token) {
redisTemplate.delete("TOKEN_" + token);
return Result.success(null);
}
如果是注册,即生成token存入redis中
/**
* 1. 判断参数 是否合法
* 2. 判断账户 是否存在,存在 ->返回账户已经存在
* 3. 不存在 -> 注册用户
* 4. 生成 token
* 5. 存入redis 并返回
* 6. 注意加事务 一旦出现问题,即回滚
*/