用户注册验证
操作步骤:(拆分需求)
1>效验参数不能为空
2>两次输入的密码是否一样
3>效验手机号码是否正确
4>效验手机号码是否唯一
5>效验短信验证码是否正确
6>注册
注意点:核心属性 必须自己控制
1>验证手机号码是否已经被注册过
controller
@GetMapping("/checkPhone")
public Object checkPhone(String phone){
return userInfoService.checkPhone(phone);
}
service (页面需要的是一个boolean值)
/**
* 通过phone 查询用户
* @param phone
* @return
*/
Boolean checkPhone(String phone);
@Override
public Boolean checkPhone(String phone) {
UserInfo userInfo = repository.findByPhone(phone);
return userInfo != null; //为空表示不存在
}
2>生成一个随机且唯一的验证码,发送给用户
#### 短信验证码发送操作逻辑:
1>点击按钮发送短信到注册那个手机号码上
2>注册手机收到短信验证码,并输入
3>低级注册携带短信验证码,判断验证码是否正确
4>将code缓存到redis对象,并设置过期时间
controller类
@GetMapping("/sendVerifyCode")
public Object sendVerifyCode(String phone){
userInfoService.sendVerifyCode(phone);
return JsonResult.success();
}
service业务层
/**
* 发送短信验证码
* @param phone
*/
void sendVerifyCode(String phone);
/**
* 发送验证码
* @param phone
*/
@Override
public void sendVerifyCode(String phone) {
//创建4位数的验证码(随机,唯一)
String code = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 4);
//拼接短信验证码提示信息
StringBuilder sb = new StringBuilder(50);
sb.append("您注册的验证码是:").append(code).append(",请在").append(Consts.VERIFY_CODE_VAI_TIME).append("分钟内提交");
//假装发短信
System.out.println(sb);
//真是发送短信本质就是使用java发起http请求即可
//RestTemplate用于发起http请求的工具类
/* RestTemplate template = new RestTemplate();
String url = "https://way.jd.com/chuangxin/dxjk?mobile={1}&content=【创信】{2}&appkey={3}";
String rep = template.getForObject(url, String.class, phone, sb.toString(), "81160ff2102302361058123544194785");
System.out.println(rep);*/
//缓存验证码
userInfoRedisService.setVerifyCode(phone, code);
}
AssertUtil工具类
public class AssertUtil {
public static void hasLength(String value,String msg){
//判断传入的数值是否为空
if(!StringUtils.hasLength(value)){
throw new LogicException(msg);
}
}
//判断两个值是否一致
public static void isEquales(String v1, String v2,String msg) {
if(v1 == null || v2 == null){
throw new LogicException(msg);
}
if(!v1.equals(v2)){
throw new LogicException(msg);
}
}
}
3>校验注册信息是否正确
操作步骤:(拆分需求)
1>效验手机号码是否正确
2>效验手机是否已经被注册
3>效验注册信息格式是否正确(非空效验,等值效验,长度效验...)
4>发送注册短信 验证码
5>用户注册
controller (根据前端带过来的数据定义 方法,参数,返回类型)
@PostMapping("/regist")
public Object regist(String phone,String nickname,String password,String rpassword,String verifyCode){
userInfoService.regist(phone,nickname,password,rpassword,verifyCode);
return JsonResult.success();
}
service业务层
/**
* 用户注册信息
* @param phone
* @param nickname
* @param password
* @param rpassword
* @param verifyCode
*/
void regist(String phone, String nickname, String password, String rpassword, String verifyCode);
@Override
public void regist(String phone, String nickname, String password, String rpassword, String verifyCode) {
//判断验证信息是否为空
AssertUtil.hasLength(phone, "手机号码不能为空");
AssertUtil.hasLength(nickname, "昵称不能为空");
AssertUtil.hasLength(password, "密码不能为空");
AssertUtil.hasLength(rpassword, "确认密码不能为空");
AssertUtil.hasLength(verifyCode, "验证码不能为空");
//验证两次输入的密码是否一样
AssertUtil.isEquales(password,rpassword);
//验证手机号码是否存在
if(this.checkPhone(phone)){
throw new LogicException("手机号码已经存在");
}
//校验短信验证码是否正确
String code = userInfoRedisService.getVerifyCode(phone);
if(!verifyCode.equalsIgnoreCase(code)){
throw new LogicException("验证码输入有误");
}
UserInfo userInfo = new UserInfo();
//把用户数据设置到对象中
userInfo.setNickname("靓仔");
userInfo.setPhone(phone);
userInfo.setEmail("123@qq.com");
userInfo.setPassword(password);
userInfo.setGender(1);//1表示男
userInfo.setLevel(0);//用户级别
userInfo.setCity("广州");
userInfo.setHeadImgUrl("/images/default.jpg");//头像路径
userInfo.setInfo("");//个性签名
userInfo.setState(0);//状态
//保存用户对象
repository.save(userInfo);
}
自定义逻辑异常
/**
* 自定义的异常
* 1:用于区分系统异常与主动抛出的异常
*/
public class LogicException extends RuntimeException{
public LogicException(String msg){
super(msg);
}
}
统一异常处理
@ControllerAdvice
public class CommonExceptionHandler {
@ExceptionHandler(LogicException.class)
@ResponseBody
public Object logicExp(Exception e, HttpServletResponse resp){
//打印捕获到的异常信息
e.getStackTrace();
//设置编码格式
resp.setContentType("application/json;charset=utf-8");
return JsonResult.error(JsonResult.CODE_ERROR_PARAM, e.getMessage(), null);
}
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public Object runtimeExp(Exception e, HttpServletResponse resp){
//打印捕获到的异常信息
e.getStackTrace();
//设置编码格式
resp.setContentType("application/json;charset=utf-8");
return JsonResult.defaultError();
}
}
4>验证通过跳转到登录界面
使用令牌方式登录流程:
1>通过请求获取username跟password,查看数据库得到用户对象user
2>通过user对象判断user是否为nll,如果是null提示信息,如果不为null表示登录成功
3>通过UUID方式创建token令牌(要求唯一,随机)
String token = UUID.randomUUID()..
4>以token为key,用户对象为user作为value缓存到redis数据库中,token的有效时间设置为30分钟
5>将token跟user对象使用接送格式返回浏览器
6>浏览器接收并解析响应数据得到token跟user对象,缓存到cookie{此时的cookie也设置有小时间是30分钟]
7>第二次访问接口时,前端发请求时,将浏览器中缓存的token数据添加到请求头中,跟请求参数一起携带到服务器
8>服务器端通过请求对象,调用getHeander("token")得到前端传过来的token数据
9>判断user对象是否为null,决定当前是否已经登录
1>如果user为null,表示没有登录
2>如果user不是null,表示已经登录
此时需要重置token的有效时间[30分钟]
controller类
@PostMapping("/login")
public Object login(String username,String password){
//通过用户传进来的 username, password 查询数据库中的用户信息
UserInfo user = userInfoService.login(username, password);
//给用户设置对应的令牌(随机,唯一)作为标识
String token = userInfoRedisService.setToken(user);
//把token,user存到reids中
HashMap<String, Object> map = new HashMap<>();
map.put("user", user);
map.put("token", token);
return JsonResult.success(map);
}
service业务层
/**
* 用户登录信息
* @param username
* @param password
* @return
*/
UserInfo login(String username, String password);
@Override
public UserInfo login(String username, String password) {
//UserInfo user = repository.findByUsernameAndPassword(username,password);
//通过用户名查询数据库中是否存在该对象
UserInfo user = repository.findByPhone(username);
//账号不存在或密码不正确,抛出异常
if(user == null || !user.getPassword().equals(password)){
throw new LogicException("账号或密码错误");
}
//为了账号安全,再返回之前把密码设置为空(在前端看控制台,不显示密码)
user.setPassword("");
return user;
}
此文及供参考,有需要的请根据自己的前端页面所需要(传入参数,返回值类型,方法映射路径修改)数据进行修改.
最后感谢您的查看,希望此文章能帮到您!