1、登陆
1)手机号密码登陆。使用的是手机号与密码的登陆,主要实现的是从数据库中的查询,不需要对手机号与密码的校验,主要实现的是一个查询的过程。主要实现代码:
/**controller层代码
* 手机号验证码登陆
* @param phone 手机号码
* @param code 验证码
* @return
*/
@RequestMapping(value="/loginByCode.json", method=RequestMethod.POST)
@ApiOperation(value = "手机号验证码登陆")
@ResponseBody
public String loginByCode(
@ApiParam(required = true, value = "手机号码") @RequestParam()String phone,
@ApiParam(required = true, value = "验证码") @RequestParam() String code) {
AppUser user = appUserService.loginByCode(phone, code);
APIPrincipal principal = APIPrincipal.of(user);
this.redisService.save(principal.getAuthentication(),principal);
return ApiResult.success(principal);
}
实现类的代码:
//手机号密码登陆
@Override
public AppUser loginByPassword(String phone, String password) {
String sql = "select * from t_app_user where phone=#{p1} and password=md5(#{p2})";
AppUser user = appUserDao.queryEx(new Sql(sql, phone, password));
if(user == null){
throw new GeneralException("手机号或密码错误");
}
if(user.getStatus()==0){
throw new GeneralException("被禁用的账号");
}
return user;
}
2)手机号验证码登录。这也是一个登录的过程个,实现的也只是查询,所以无需对手机号进行校验,我们要校验的只是验证码,在登录完成之后我们需要删除缓存中的验证码,下次登录就需要从新获取验证码。代码实现:
/**
controller层代码:
* 手机号验证码登陆
* @param phone 手机号码
* @param code 验证码
* @return
*/
@RequestMapping(value="/loginByCode.json", method=RequestMethod.POST)
@ApiOperation(value = "手机号验证码登陆")
@ResponseBody
public String loginByCode(
@ApiParam(required = true, value = "手机号码") @RequestParam()String phone,
@ApiParam(required = true, value = "验证码") @RequestParam() String code) {
AppUser user = appUserService.loginByCode(phone, code);
APIPrincipal principal = APIPrincipal.of(user);
this.redisService.save(principal.getAuthentication(),principal);
return ApiResult.success(principal);
}
实现类层的代码:
//验证码登录
@Override
public AppUser loginByCode(String phone, String code) {
//验证码的校验
String key = SendCodeType.Login.getDesc()+phone;
String sendCode = redisService.get(key, String.class);
if(StringUtils.isEmpty(sendCode) || !sendCode.equals(code)){
throw new GeneralException("验证码错误");
}
String sql="select * from t_app_user where phone=#{p1}";
AppUser user=appUserDao.queryEx(new Sql(sql,phone));
if(user==null){
throw new GeneralException("此手机号未注册");
}
if(user.getStatus()==0){
throw new GeneralException("被禁用的账号");
}
redisService.delete(key);
return user;
}
3)忘记密码手机号校验。(1)先通过用户输入的手机号去数据库中查询是否存在该号码,如果存在,就给其一个验证码,接下来就是对验证码的的校验。要是不存在就提示用户手机号尚未注册,重新输入。我们需要把用户的信息,手机号和当前用户的id存储到缓存中以key-value的形式存储(授权码,用户信息),最后返回授权码。代码实现:
/**
* 忘记密码手机号校验
* @param phone 手机号码
* @param code 验证码
* @return
*/
@RequestMapping(value = "/forgetPassword.json", method = RequestMethod.POST)
@ApiOperation(value = "忘记密码手机号校验",notes="返回重置密码的token")
public @ResponseBody String checkPhoneWithForgetPassword(
@ApiParam(required = true, value = "手机号") @RequestParam() String phone,
@ApiParam(required = true, value = "验证码") @RequestParam() String code
) {
String key = SendCodeType.ForgetPassword.getDesc()+phone;
String sendCode = redisService.get(key, String.class);
if(StringUtils.isEmpty(sendCode) || !sendCode.equals(code)){
return ApiResult.error("验证码错误");
}
AppUser user =this.appUserService.find("phone",phone);
if(user == null) {
return ApiUtils.error("验证的手机号码未注册");
}
String token = APIPrincipal.UUID();
Map<String,String> info = new HashMap<String,String>();
info.put("phone", phone);
info.put("userId", user.getId()+"");
redisService.save(token, info, 1800);
redisService.delete(key);
return ApiUtils.success(token);
}
(2)手机号校验成功之后,修改当前用户的密码。密码的校验比较常见,所以提取出来成为工具类。代码实现:
//重置密码controller层代码
@RequestMapping(value = "/resetPassword.json", method = RequestMethod.POST)
@ApiOperation(value = "忘记密码重置密码")
@ResponseBody
public String resetPassword(
@ApiParam(required = true, value = "新密码") @RequestParam() String newPassword,
@ApiParam(required = true, value = "重置密码的token") @RequestParam() String token
) {
appUserService.resetPassword(newPassword, token);
return ApiUtils.success();
}
//实现类测代码
//重置密码
@Override
public int resetPassword(String newPassword, String token) {
@SuppressWarnings("unchecked")
//从缓存中取出当前用户的信息(手机号+当前用户的id)
Map<String,String> info = redisService.get(token, Map.class);
if(info==null){
throw new GeneralException("请先校验手机号码,然后重置密码");
}
//校验密码
ValidUtil.validPassword(newPassword, "密码格式错误,6-16位数字、字母或下划线");
//从缓存中取出手机号码
String phone = info.get("phone");
//取出缓存中的当前用户id转换成userid
Long userId = Long.valueOf(info.get("userId"));
//修改当前用户的密码
int res = mapper.executeEx(
new Sql("update t_app_user set password=MD5(#{p1}) where phone=#{p2}",
newPassword,
phone));
if(res>0) {
redisService.delete(token);
//删除缓存中的所有登录信息,从新去登录
redisService.deleteKeys(APIPrincipal.PREFIX_USER_SESSION+ userId +"_*");
}
return res;
}
工具类:
package com.framework.loippi.utils;
import java.util.List;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import com.framework.loippi.exception.GeneralException;
public class ValidUtil {
public static String getErrorMsg(List<ObjectError> errorList) {
StringBuilder msg = new StringBuilder("");
for(ObjectError e : errorList) {
if(e instanceof FieldError) {
FieldError fieldError = (FieldError)e;
msg.append(fieldError.getField());
}
msg.append(e.getDefaultMessage()).append(",");
}
return msg.toString();
}
/**
* 手机号码校验 "^1((3[\d])|(4[5,6,9])|(5[0-3,5-9])|(6[5-7])|(7[0-8])|(8[1-3,5-8])|(9[1,8,9]))\d{8}$"
* @param phone 手机号
* @return
*/
public static boolean validPhone(String phone) {
if(phone == null) {
return false;
}
String reg="^1((3[\\d])|(4[5,6,9])|(5[0-3,5-9])|(6[5-7])|(7[0-8])|(8[1-3,5-8])|(9[1,8,9]))\\d{8}$";
return phone.matches(reg);
}
/**
* 手机号码校验 "^1[345678]\\d{9}$"
* @param phone 手机号码
* @param errorMsg 校验失败则抛出异常信息
*/
public static void validPhone(String phone, String errorMsg) {
if(!validPhone(phone)) {
throw new GeneralException(errorMsg);
}
}
/**
* 密码校验 "^\\w{6,16}$"
* @param password 密码
* @return
*/
public static boolean validPassword(String password) {
if(password == null) {
return false;
}
String reg = "^\\w{6,16}$";
return password.matches(reg);
}
/**
* 密码校验 "^\\w{6,16}$"
* @param password 密码
* @param errorMsg 校验失败则抛出异常信息
*/
public static void validPassword(String password, String errorMsg) {
if(!validPassword(password)) {
throw new GeneralException(errorMsg);
}
}
}
2、注册
1)先对手机号进行校验,看数据库中是否已经存在,或者是手机号码是否正确。便于测试,我们就在公共的控制层中给验证码写死了,所以,手机号这里就省略不写了。因为校验在公共的控制层已经写了,代码实现:
/*controller层代码
* 注册
* @param phone 手机号
* @param code 验证码
* @return
*/
@RequestMapping(value = "/regist.json", method = RequestMethod.POST)
@ApiOperation(value="注册", notes="返回设置密码的token")
@ResponseBody
public String regist(
@ApiParam(required = true, value = "手机号码") @RequestParam() String phone,
@ApiParam(required = true, value = "验证码") @RequestParam() String code
) {
appUserService.regist(phone, code);
String token = APIPrincipal.UUID();
redisService.save(token, phone);
return ApiUtils.success(token);
}
实现类层代码:
//注册
@Override
public int regist(String phone, String code) {
String key=SendCodeType.Regist.getDesc()+phone;
String sendCode=redisService.get(key, String.class);
if(StringUtils.isEmpty(sendCode)|| !sendCode.equals(code)){
throw new GeneralException("验证码错误");
}
AppUser user = this.find("phone", phone);
if(user != null){
throw new GeneralException("该手机号已注册");
}
user = new AppUser();
user.setPhone(phone);
appUserDao.insert(user);
redisService.delete(key);
return 0;
}
2)手机号校验成功之后,就需要点击下一步去设置密码;代码实现:
/**controller 层代码
* 设置密码
* @param authentication 注册成功后返回的认证码
* @param password 密码
* @return
*/
@RequestMapping(value = "/setPassword.json", method = RequestMethod.POST)
@ApiOperation(value = "设置密码")
@ResponseBody
public String setPassword(
@ApiParam(required = true, value = "密码") @RequestParam() String password,
@ApiParam(required = true, value = "授权码") @RequestParam() String token
) {
appUserService.setPassword(password, token);
return ApiResult.success();
}
实现类的代码:
//重置密码
@Override
public int setPassword(String password, String token) {
ValidUtil.validPassword(password, "密码格式错误,6-16位数字、字母或下划线");
String phone= redisService.get(token,String.class);
if(StringUtils.isEmpty(phone)) {
return 0;
}
return mapper.executeEx(new Sql(
"update t_app_user set password=MD5(#{p1}) where phone=#{p2}",
password, phone));
}