西安市建设局官方网站网络营销网站平台有哪些
1.代码逻辑流程图:
这里存储用户信息使用hash结构进行存储。 使用String和json存储不是那么方便。
因为原本使用session的方案会自动帮我们进行校验,这里我们使用redis进行代替有很多东西都需要我们自己去存储。前端会把token存放在请求头中,我们每次校验的使用从请求头中获取即可。
2.发送验证码的代码:
public Result sendCode(String phone, HttpSession session) {// 校验手机号if(RegexUtils.isPhoneInvalid(phone)){// 如果不符合,返回错误信息return Result.fail("手机号格式错误");}// 符合生成验证码String code = RandomUtil.randomNumbers(6);// 保存验证码到redis中stringRedisTemplate.opsForValue().set(RedisConstants.LOGIN_CODE_KEY + phone, code,RedisConstants.LOGIN_CODE_TTL,TimeUnit.MINUTES);// 发送验证码log.debug("发送验证码成功,验证码:{}",code);return Result.ok();
}
3.重新实现登录的代码:
public Result login(LoginFormDTO loginForm, HttpSession session) {// 校验手机号和验证码String phone = loginForm.getPhone();if(RegexUtils.isPhoneInvalid(phone)){// 如果不符合,返回错误信息return Result.fail("手机号格式错误");}// 从redis中获取验证码并校验验证码String cacheCode = stringRedisTemplate.opsForValue().get(RedisConstants.LOGIN_CODE_KEY + phone);String code = loginForm.getCode();if(cacheCode == null || !cacheCode.equals(code)){return Result.fail("验证码错误");}// 根据手机号查询用户User user = query().eq("phone",phone).one();if(user == null){user = createUserWithPhone(phone);}//保存用户信息到redis中String token = UUID.randomUUID().toString(true);String tokenKey = RedisConstants.LOGIN_USER_KEY + token;UserDTO userDTO = BeanUtil.copyProperties(user,UserDTO.class);Map<String, Object> userMap = BeanUtil.beanToMap(userDTO,new HashMap<>(), CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((fieldName,fieldValue) -> fieldValue.toString())); // 把User转换成mapstringRedisTemplate.opsForHash().putAll(tokenKey,userMap);//存储用户信息stringRedisTemplate.expire(tokenKey,RedisConstants.LOGIN_USER_TTL,TimeUnit.MINUTES); // 设置有效期return Result.ok(token);
}
4.重新实现登录校验的代码逻辑:
这里就是重新实现拦截器的代码
public class RefreshTokenInterceptor implements HandlerInterceptor {private StringRedisTemplate stringRedisTemplate;public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate = stringRedisTemplate;}public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 1.获取请求头中的tokenString token = request.getHeader("authorization");if (StrUtil.isBlank(token)) {return true;}// 2.基于TOKEN获取redis中的用户String key = LOGIN_USER_KEY + token;Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key);// 3.判断用户是否存在if (userMap.isEmpty()) {return true;}// 5.将查询到的hash数据转为UserDTOUserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);// 6.存在,保存用户信息到 ThreadLocalUserHolder.saveUser(userDTO);// 7.刷新token有效期stringRedisTemplate.expire(key, LOGIN_USER_TTL, TimeUnit.MINUTES);// 8.放行return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 移除用户UserHolder.removeUser();}
}
这里因为我们设置的token有过期删除时间,所以我们每次操作经过拦截器的时候,都需要刷新过期时间。然后因为有的接口因没有使用拦截器但是我们也需要刷新过期时间,所以建议把更新过期时间和拦截未登录用户写成两个拦截器。但是这里的代码是写在一起的,可以自己改一下。