前言
上一章的登录接口,我们将用户登录信息放置于Map中,存在一个问题,集群部署无法共享以及应用停止用户登录信息即丢失,接下来我们整合redis来整合这个问题。
一、整合redis
1. 引入库
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2. 配置
spring:
data:
redis:
host: 192.168.137.192
port: 6379
database: 0
username: default
password: 21797d7480c1270b848a1524128671b31dcad0725762cf41cc81c21e15fa35b2
二、登录优化
1.登录
@Autowired
StringRedisTemplate stringRedisTemplate;
@RequestMapping("login")
public Result login(@Valid User loginUser){
String message="用户名/密码不正确";
User user = userSerivce.findUserByName(loginUser.getUsername());
if(user!=null){//用户存在
if(user.getPassword().equals(Md5Util.getMD5String(loginUser.getPassword()))){//密码正确
Map<String,Object> claims=new HashMap();
claims.put("userId",user.getId());
claims.put("username",user.getUsername());
String token = JwtUtils.create(claims);
stringRedisTemplate.opsForValue().set(user.getId().toString(),token,24, TimeUnit.HOURS);
return Result.success("登录成功",token);
}
}
return Result.error(message);
}
2.拦截器
@Autowired
StringRedisTemplate stringRedisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("Authorization");
if(token!=null&&token.contains("Bearer")){
String tokenStr = token.substring(token.indexOf("Bearer") + 7);
boolean verify = JwtUtils.verify(tokenStr);
if(verify){//此处解析loginUsers,验证用户已登录
Map<String, Object> claims = JwtUtils.getClaims(tokenStr);
if(tokenStr.equals(stringRedisTemplate.opsForValue().get(claims.get("userId").toString()))){
ThreadLocalUtil.set(claims);//用户信息放置ThreadLocal
return true;
};
}
}
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setContentType("application/json;charset=UTF-8");
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writerFor(Result.class);
String message = objectMapper.writeValueAsString(Result.error("token验证失败,请重新获取token后重试!"));
response.getWriter().println(message);
return false;
}
3. 登出
@RequestMapping("logout")
public Result logout(@Valid User loginUser,@RequestHeader("Authorization") String token){
String message="用户名/密码不正确";
User user = userSerivce.findUserByName(loginUser.getUsername());
if(user!=null){//用户存在
if(token!=null&&token.contains("Bearer")){
String tokenStr = token.substring(token.indexOf("Bearer") + 7);
boolean verify = JwtUtils.verify(tokenStr);
if(verify&&tokenStr.equals(loginInceptor.get(user.getId()))){
// loginInceptor.remove(user.getId());
stringRedisTemplate.delete(user.getId().toString());
return Result.success("登出成功");
}
}
}
return Result.error(message);
}
4. 修改密码
@PatchMapping("updatePwd")
public Result updatePwd(@RequestBody Map<String,String> params){
String oldPwd = params.get("old_pwd");
String newPwd = params.get("new_pwd");
String conPwd = params.get("con_pwd");
//参数校验
if(!StringUtils.hasLength(oldPwd)||!StringUtils.hasLength(newPwd)||!StringUtils.hasLength(conPwd)){
return Result.error("缺少必要的参数");
}
if(!validPwdLen(oldPwd)||!validPwdLen(newPwd)||!validPwdLen(conPwd)){
return Result.error("密码为8-20位");
}
//密码匹配
Map<String, Object> claims =ThreadLocalUtil.get();
Integer userId = (Integer) claims.get("userId");
User user = userSerivce.findUserById(userId);
if(!Md5Util.getMD5String(oldPwd).equals(user.getPassword())){
return Result.error("密码有误");
}
//新密码匹配
if(!newPwd.equals(conPwd)){
return Result.error("两次密码不匹配");
}
//新旧匹配
if(newPwd.equals(oldPwd)){
return Result.error("新旧密码不能相同");
}
user.setPassword(Md5Util.getMD5String(newPwd));
int i = userSerivce.UpdateUser(user);
if(i!=1){
return Result.success("密码修改失败");
}
stringRedisTemplate.delete(user.getId().toString());
return Result.success("密码修改成功");
}