模块一:登录模块

模块一:登录模块

发送验证码

Controller层

    /**
     * 发送手机验证码
     */
    @PostMapping("code")
    public Result sendCode(@RequestParam("phone") String phone, HttpSession session) {
        return userService.sendCode(phone, session);
    }

Service接口

public interface IUserService extends IService<User> {
    Result sendCode(String phone, HttpSession session);
}

**Service接口实现类 **

@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Result sendCode(String phone, HttpSession session) {
        //1.校验手机号
        if (RegexUtils.isPhoneInvalid(phone)){
            //2.如果不符合,返回错误信息
            return Result.fail("手机号格式错误!");
        }
        //3.符合生成验证码
        String code = RandomUtil.randomNumbers(6);
        //4.保存到redis中	login:code
        stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY + phone, code, LOGIN_CODE_TTL, TimeUnit.MINUTES);
        //5.发送验证码
        log.debug("发送短信验证码成功,验证码:{}", code);
        //6.返回ok
        return Result.ok();
    }

短信验证登录、注册

Controller层

/**
     * 登录功能
     * @param loginForm 登录参数,包含手机号、验证码;或者手机号、密码
     */
    @PostMapping("/login")
    public Result login(@RequestBody LoginFormDTO loginForm, HttpSession session){
        return userService.login(loginForm, session);
    }

Service接口

public interface IUserService extends IService<User> {
    Result login(LoginFormDTO loginForm, HttpSession session);
}

Service接口实现类

@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Result login(LoginFormDTO loginForm, HttpSession session) {
        //1.校验手机号
        String phone = loginForm.getPhone();
        if(RegexUtils.isPhoneInvalid(phone)){
            //2.如果不符合,返回错误信息
            return Result.fail("手机号格式错误!");
        }
        //3.从redis中获取验证码并且校验
        String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);
        String code = loginForm.getCode();
        if(cacheCode == null || !cacheCode.equals(code)){
            return Result.fail("验证码错误");
        }
        //3.一致,根据手机号查询用户  MyBatisPlus实现单表查询(要看一下)
        User user = query().eq("phone", phone).one();
        //4.判断用户是否存在
        if(user == null){
            user = createUserWithPhone(phone);
        }
        //5.判断用户是否存在
        if (user == null) {
            //6.创建用户保存
            session.setAttribute("user", user);
        }
        //7.1随机生成token作为登录令牌
        String token = UUID.randomUUID().toString(true);
        //7.2将User对象转为Hash存储
        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
        Map<String, Object> userMap = BeanUtil.beanToMap(userDTO, new HashMap<>(),		//处理非String类型数据
                CopyOptions.create()
                    .setIgnoreNullValue(true)
                    .setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString()));
        //7.3存储
        String tokenKey = LOGIN_USER_KEY + token;
        stringRedisTemplate.opsForHash().putAll(tokenKey, userMap);
        //设置token有效期
        stringRedisTemplate.expire(LOGIN_USER_KEY, LOGIN_USER_TTL, TimeUnit.MINUTES);
        return Result.ok(token);
    }

    private User createUserWithPhone(String phone) {
        User user = new User();
        user.setPhone(phone);
        user.setNickName(USER_NICK_NAME_PREFIX + RandomUtil.randomString(10));
        save(user);
        return user;
    }
}

拦截器

拦截器(2个)注册部分

@Configuration
public class MvcConfig implements WebMvcConfigurer {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //登录拦截器
        registry.addInterceptor(new LoginInterceptor())
        .excludePathPatterns(
                "/user/code",
                "/user/login",
                "/blog/hot",
                "/shop/**",
                "/shop-type/**",
                "/upload/**",
                "/voucher/**"
        ).order(1);
        //token刷新拦截器,设置为优先拦截
        registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)).addPathPatterns("/**").order(0);
    }
}

登录部分-拦截器

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.判断是否需要拦截(TreadLocal中是否有用户)
        if(UserHolder.getUser() == null){
            //没有,需要拦截,设置状态码
            response.setStatus(401);
            //拦截
            return false;
        }
        //有用户,则放行
        return true;
    }
}

刷新token-拦截器

public class RefreshTokenInterceptor implements HandlerInterceptor {
    /**
     * 注意此处只能使用构造函数的方式进行注入
     * LoginInterceptor类的对象是手动new出来的
     * spring创建的对象可以帮助依赖注入,自己手动创建的对象没人帮你依赖注入
     */
    private StringRedisTemplate stringRedisTemplate;

    public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.获取请求头中的token
        String token = request.getHeader("authorization");
        if(StrUtil.isBlank(token)){
            return true;
        }
        //2.基于token获取redis中的用户
        String key = RedisConstants.LOGIN_USER_KEY + token;
        Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key);

        //3.判断用户是否存在
        if (userMap.isEmpty()){
            return true;
        }
        //5.将查询到的hash数据转为UserDTO对象
        UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);
        //6.存在,保存用户信息到TreadLocal中
        UserHolder.saveUser(userDTO);
        //7.刷新token有效期
        stringRedisTemplate.expire(key, RedisConstants.LOGIN_USER_TTL, TimeUnit.MINUTES);
        //8.放行
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserHolder.removeUser();
    }
}

相关推荐

  1. 模块登录模块

    2024-06-17 23:12:04       29 阅读
  2. 关于二手车系统学习--登录模块

    2024-06-17 23:12:04       23 阅读
  3. os模块篇(十

    2024-06-17 23:12:04       29 阅读
  4. 嵌入式—模块代码()

    2024-06-17 23:12:04       35 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-17 23:12:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-17 23:12:04       100 阅读
  3. 在Django里面运行非项目文件

    2024-06-17 23:12:04       82 阅读
  4. Python语言-面向对象

    2024-06-17 23:12:04       91 阅读

热门阅读

  1. python实践笔记(二): 类和对象

    2024-06-17 23:12:04       27 阅读
  2. 揭秘创业加盟:豫腾助力,发掘商机,共赢未来

    2024-06-17 23:12:04       32 阅读
  3. IMP和引用码 位置关系

    2024-06-17 23:12:04       33 阅读
  4. 第一章 - 第10节- 计算机网络 - 课后习题

    2024-06-17 23:12:04       27 阅读
  5. 【Linux】shell——传递参数

    2024-06-17 23:12:04       22 阅读