您的当前位置:首页正文

【Redis】实现短信验证码登录和注册功能

2024-11-07 来源:个人技术集锦

一、页面流程


二、代码实现

实体类

@Data
public class LoginFormDTO {
    private String phone;
    private String code;
    private String password; // 既支持使用手机号登录,又支持使用密码登录
}

UserController.java

/**
 * 登录功能
 * @param loginForm 登录参数,包含手机号、验证码;或者手机号、密码
 */
@PostMapping("/login")
// 由于这里使用了RequestBody,使用的是JSON风格,因此后台接收就必须使用这个注解
public Result login(@RequestBody LoginFormDTO loginForm, HttpSession session){
    // 实现登录功能
    return userService.login(loginForm, session);
}

UserService.java

登录,这里登录其实是分为两部分的,因为如果用户输入的手机号不存在,就会立即给它创建一个手机号,这样用户就不用有繁琐的注册流程了。

技巧:校验一般都是反向校验,这样可以避免if嵌套越来越深。

@Override
public Result login(LoginFormDTO loginForm, HttpSession session) {
    // 1.校验手机号,虽然手机号在发送验证码的请求中已经校验过一次了,但由于这是两个不同的请求,每一个请求都需要做独立的校验。
    // 万一发短信的时候它填一个正确的,后来点登录按钮的时候它又填个错误的也有可能。
    String phone = loginForm.getPhone();
    if (RegexUtils.isPhoneInvalid(phone)) {
        // 2.如果不符合,返回错误信息
        return Result.fail("手机号格式错误!");
    }
    // 3.校验验证码
    // PS:像"code"这种字符串常量应该定义成一个常量值放到一个专门的地方去,这里为了方便就这样写了
    // 由于是从session中取到的,因此取名为cacheCode,代表是缓存起来的。
    Object cacheCode = session.getAttribute("code");
    String code = loginForm.getCode(); // 这个code才是前端传递过来的code
    if(cacheCode == null || !cacheCode.toString().equals(code)){
        //3.不一致,报错
        return Result.fail("验证码错误");
    }
    //一致,根据手机号查询用户,因为手机号是唯一的,并且数据库表中也限定了手机号是UNIQUE
    // select * from tb_user where phone = ?
    // query()是mybatis-plus提供的,它可以帮我们实现单表增删改查,它是知道我们的表叫tb_user的,因为实体类中有注解,紧接着eq("phone", phone)就是写where条件,如果查多个就使用list,它的返回值是一个集合,但如果查一个就用one(),它的返回值就是User
    User user = query().eq("phone", phone).one();

    //5.判断用户是否存在
    if(user == null){
        //不存在,则创建
        user =  createUserWithPhone(phone);
    }
    //7.保存用户信息到session中
    session.setAttribute("user",user);

    return Result.ok();
}

private User createUserWithPhone(String phone) {
    // 创建用户
    User user = new User();
    user.setPhone(phone);
    // 这里用户名就随机生成,由于工具类随机生成的字符串会看起来很混乱,因此加一个前缀,这样用户名会看起来更统一一些
    // 这个前缀最好也定义成常量,在我们在自己定义的常量类SystemConstants中有一个USER_NICK_NAME_PREFIX,它的值就是user_,即前缀
    // 像京东那些,如果你第一次使用手机号登录,它都会给你生成一个有规律的用户名称
    user.setNickName(SystemConstants.USER_NICK_NAME_PREFIX + RandomUtil.randomString(10));
    // 调用MybatisPlus的save方法保存用户到数据库
    save(user);
    // 返回已经创建的用户
    return user;
}

在登录的时候是不需要返回登录凭证的,因为这里是基于session登录,session的原理就是cookie,每一个session都会有一个唯一的sessionId,你访问tomcat的时候,这个sessionId就已经自动的写到你的cookie中了,以后请求就会带着这个sessionId,带着这个sessionId过来我们就能找到session,找到session就能找到这个用户了。

显示全文