@PostMapping("code")
public Result sendCode(@RequestParam("phone") String phone, HttpSession session) {
// 发送短信验证码并保存验证码
// 1. 验证手机号
if (RegexUtils.isPhoneInvalid(phone)) {
return Result.fail("手机格式不对");
}
// 2. 生成验证码
String code = RandomUtil.randomNumbers(6);
// 3. 保存验证码
stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY + phone, code,
LOGIN_CODE_TTL, TimeUnit.MINUTES);
// 4. 发送验证码
// session.setAttribute("code", phone + "_" + code);
log.info("验证码发送成功:" + code);
return Result.ok("生成验证码成功");
}
@PostMapping("/login")
public Result login(@RequestBody LoginFormDTO loginForm, HttpSession session){
// 实现登录功能
// 1. 验证验证码
String phone = loginForm.getPhone();
String submit_code = loginForm.getCode();
// Object code = session.getAttribute("code");
String code = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);
if(code == null || !code.equals(submit_code)) {
return Result.fail("验证码不正确");
}
// 2. 根据手机号进行登陆
UserDTO user = userService.login(phone);
// 3. **存储用户到redis里面去**
String uuid = UUID.randomUUID().toString();
Map<String, Object> map = BeanUtil.beanToMap(user, new HashMap<>(),
CopyOptions.create().setIgnoreNullValue(true)
.setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString()));
stringRedisTemplate.opsForHash().putAll(LOGIN_USER_KEY + uuid, map);
stringRedisTemplate.expire(LOGIN_USER_KEY+ uuid, LOGIN_USER_TTL, TimeUnit.MINUTES);
// session.setAttribute("user", user);
return Result.ok(uuid);
}
<aside> 💡 BeanUtil.beanToMap 将Bean转换为一个Map,然后存储到Redis的Hash进去。
</aside>
状态刷新拦截器
public class InterceptorRefresh implements HandlerInterceptor {
private StringRedisTemplate stringRedisTemplate;
public InterceptorRefresh(StringRedisTemplate _stringRedisTemplate) {
this.stringRedisTemplate = _stringRedisTemplate;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 1. 获取请求头的token
String authorization = request.getHeader("authorization");
// 2. 如果token为空,直接返回
if(StrUtil.isBlank(authorization)) {
return true;
}
// 3. 判断用户是否存在
Map<Object, Object> map = this.stringRedisTemplate.opsForHash().entries(LOGIN_USER_KEY + authorization);
if(map.isEmpty()) {
return true;
}
// 4. 进行转换
UserDTO userDTO = BeanUtil.fillBeanWithMap(map, new UserDTO(), false);
// 5. 登陆存储用户
UserHolder.saveUser(userDTO);
// 6. 刷新有效期
stringRedisTemplate.expire(LOGIN_USER_KEY + authorization, LOGIN_USER_TTL, TimeUnit.MINUTES);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
UserHolder.removeUser();
}
}
登陆验证拦截器
public class InterceptorLogin implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if(UserHolder.getUser() == null) {
return false;
}
return true;
}
}
注册拦截器
按照顺序依次拦截
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Resource
StringRedisTemplate stringRedisTemplate;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new InterceptorRefresh(stringRedisTemplate));
registry.addInterceptor(new InterceptorLogin())
.excludePathPatterns(
"/shop/**",
"/voucher/**",
"/shop-type/**",
"/upload/**",
"/blog/hot",
"/user/code",
"/user/login"
);
}
}
@GetMapping("/me")
public Result me(){
// 获取当前登录的用户并返回
UserDTO user = UserHolder.getUser();
return Result.ok(user);
}