实体类
@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就能找到这个用户了。