《智叟出行》app之前的后台功能并不完善,因此打算用这段时间对后台代码进行重构,顺便完善一些新的功能,并给未来可能会添加的新功能预留接口。
注册登陆模块重构
注册登录模块原本打算使用微信登录实现,这样不仅符合一键注册/登录的优雅,同时操作十分的简洁方便,适合老年人使用。然而,微信登录需要在微信开放平台注册APP,而且还要app官网地址…所以目前看来是不能搞到appid和appsecret了…于是只能改为普通的登录注册,找回密码
1.需求分析
用例1 - 用户登录
描述 | 用户通过登录以访问app |
---|---|
主要参与者 | 用户 |
前置条件 | 用户输入手机号与密码,并且系统正常运行 |
步骤 | 1.用户登录页面。2.用户输入有效的手机号和密码。3.用户点击登陆。 |
后置条件 | 用户成功登录后,显示app首页 |
用例2 - 用户注册
描述 | 用户通过注册拥有账号以登录访问app |
---|---|
主要参与者 | 用户 |
前置条件 | 用户输入用户名,手机号与密码,并且系统正常运行 |
步骤 | 1.用户注册页面。2.用户输入有效的用户名,手机号和密码。3.用户点击注册。 |
后置条件 | 用户成功注册后,回到登陆页 |
用例3 - 用户登陆状态实时检测
描述 | 用户登录之后,token有效期之内可以正常访问,一旦过期,应该回到登录页面 |
---|---|
主要参与者 | 用户 |
前置条件 | 用户令牌过期,并且系统正常运行 |
步骤 | 1.用户令牌过期。2.弹出提示框提示重新登陆。3.用户点击确定。 |
后置条件 | 用户回到登陆页 |
2.接口设计
2.1 用户登录

用户登陆接口实现逻辑
@Override
public UserLoginVO login(UserLoginDTO userLoginDTO) {
//检查用户是否存在,不存在抛出用户不存在的异常
User user=userMapper.getByPhone(userLoginDTO.getPhone());
if(user==null){
throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
}
//用户存在,校验登陆密码,
String dtoPassword= DigestUtils.md5DigestAsHex(userLoginDTO.getPassword().getBytes());
log.info("加密后密码:{}",dtoPassword);
log.info("数据库的密码:{}",user.getPassWord());
if(!dtoPassword.equals(user.getPassWord())) {
throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
}
//生成jwt-token,并将userId设置进去,同时也将token有效时间和生成时间设置进去,前端会自动检测过期时间
Map<String,Object> claims=new HashMap<>();
claims.put(JwtClaimsConstant.USER_ID,user.getUserId());
String token=JwtUtil.createJWT(jwtProperties.getUserSecretKey(),jwtProperties.getUserTtl(),claims);
//获取当前时间的时间戳
Long timestamp=System.currentTimeMillis();
Long tokenValidTime=jwtProperties.getUserTtl();
//生成返回对象
UserLoginVO userLoginVO=UserLoginVO.builder()
.userId(user.getUserId())
.token(token)
.tokenCreateTime(timestamp)
.tokenValidTime(tokenValidTime)
.build();
return userLoginVO;
}
2.2 用户注册

用户注册接口实现逻辑
/**
* 用户注册
* @param userRegisterDTO
*/
@Override
public void register(UserRegisterDTO userRegisterDTO) {
//不能使用重复的手机号注册
User user=userMapper.getByPhone(userRegisterDTO.getPhone());
if(user!=null){
throw new AccountExistsException(MessageConstant.ACCOUNT_EXISTS);
}
//创建一个新的账户
User account=User.builder()
.userName(userRegisterDTO.getUsername())
.phone(userRegisterDTO.getPhone())
.passWord(userRegisterDTO.getPassword())
.createTime(LocalDateTime.now())
.build();
userMapper.insert(account);
}
3.前端详细设计
主要记录针对检测用户登陆状态的设计。对于用户状态实时检测,我使用了定时器设置,在前端用户输入完手机号和密码之后,发送登陆请求,请求成功之后,设置定时器,定时器每隔10秒检测一次登陆令牌是否过期。
用户登陆逻辑
userLogin: function() {
var form = {
"phone": this.phone,
"password": this.password
}
login(form).then(res => {
// 请求成功
var token = res.data.token;
// 将拿到的token存入缓存中;
uni.setStorageSync("token", token);
// 启动计时器,实时监测token是否过期
var creatTime = res.data.tokenCreateTime;
var validTime = res.data.tokenValidTime;
// 跳转页面
uni.switchTab({
url: '/pages/index/index',
success: () => {
// 页面跳转成功后启动计时器
tokenTimer(creatTime, validTime);
}
});
}).catch(err => {
console.log("请求失败");
});
}
定时器,动态监测token过期时间
//定时器,动态监测token过期时间
export function tokenTimer(tokenCreateTime, tokenValidTime) {
// 每隔一定的时间间隔执行检查
var intervalId=setInterval(() => {
if (!checkTokenValidity(tokenCreateTime, tokenValidTime)) {
// 如果 Token 过期,则弹出提示窗口
uni.showModal({
content: '用户认证已过期,需要重新登录',
showCancel: false,
success: function(res) {
// 用户点击了确认按钮,关闭定时器
clearInterval(intervalId);
// 跳转到登录页面
uni.navigateTo({
url: "/pages/user/login"
})
}
})
}
}, 10000); // 这里设置为每10秒检查一次,你可以根据实际需求调整时间间隔
}
利用后端传递过来的token创建时间戳和token有效时间,计算当前时间token是否过期
function checkTokenValidity(tokenCreateTime, tokenValidTime) {
var currentTime = new Date().getTime(); //获取当前时间的时间戳
var pastTime = tokenCreateTime;
// 计算时间差(毫秒数)
var timeDiff = currentTime - pastTime;
var flag = true;
if (timeDiff > tokenValidTime) {
flag = false;
}
return flag;
}