用户登录流程
代码实现
@Override
public ResponseResult doLogin(String captcha,
String captchaKey,
SobUser sobUser,
HttpServletRequest request,
HttpServletResponse response) {
String captchaValue = (String) redisUtils.get(Constants.User.KEY_CAPTCHA_CONTENT + captchaKey);
if (!captcha.equals(captchaValue)) {
return ResponseResult.FAILED("人类验证码不正确");
}
//有可能是邮箱,也有可能是用户名
String userName = sobUser.getUserName();
if (TextUtils.isEmpty(userName)) {
return ResponseResult.FAILED("账号不可以为空.");
}
String password = sobUser.getPassword();
if (TextUtils.isEmpty(password)) {
return ResponseResult.FAILED("密码不可以为空.");
}
SobUser userFromDb = userDao.findOneByUserName(userName);
if (userFromDb == null) {
userFromDb = userDao.findOneByEmail(userName);
}
if (userFromDb == null) {
return ResponseResult.FAILED("用户名或密码不正确");
}
//用户存在
//对比密码
boolean matches = bCryptPasswordEncoder.matches(password, userFromDb.getPassword());
if (!matches) {
return ResponseResult.FAILED("用户名或密码不正确");
}
//密码是正确
//判断用户状态,如果是非正常的状态,则返回结果
if (!"1".equals(userFromDb.getState())) {
return ResponseResult.FAILED("当前账号已被禁止.");
}
createToken(response, userFromDb);
return ResponseResult.SUCCESS("登录成功");
}
createToken的代码
创建了两个token,一个是token,一个是refreshToken
为什么要两个tokne呢?
为什么要用两个token?
假设我们只用一个token--->
生成一个token-->有效期:2小时--->每次访问就更新---> 两个小时没有访问的话,就会要重新登录
生成一个token-->有效期:30天---->每次访问都会更新--->用户一个月没有登录,没有访问,就会过期 --->如果这个token长期保存在redis里,会占用资源。这个用户一个月才访问一次,这样就浪费资源了。
生成一个token--->有效期2个小时,保存在redis里--->过期了,我们就通过refreshToken来创建新的token-->redis 里,如果你两个小时不访问,那么redis里的token会被干掉,这样就不占用redis的资源了。如果再访问,通过refreshToken来创建新的token。如果该用户一个月没有访问,要重新登录。因为refreshToken有效期为30天。
为什么不直接使用RefreshToken--->保存在Mysql里的--->Mysql的查询速度没有Redis快
/**
* @param response
* @param userFromDb
* @return token_key
*/
private String createToken(HttpServletResponse response, SobUser userFromDb) {
int deleteResult = refreshTokenDao.deleteAllByUserId(userFromDb.getId());
log.info("deleteResult of refresh token .. " + deleteResult);
//生成token
Map<String, Object> claims = ClaimsUtils.sobUser2Claims(userFromDb);
//token默认有效为2个小时
String token = JwtUtil.createToken(claims);
//返回token的md5值,token会保存到redis里
//前端访问的时候,携带token的md5key,从redis中获取即可
String tokenKey = DigestUtils.md5DigestAsHex(token.getBytes());
//保存token到redis里,有效期为2个小时,key是tokenKey
redisUtils.set(Constants.User.KEY_TOKEN + tokenKey, token, Constants.TimeValue.HOUR_2);
//把tokenKey写到cookies里
//这个要动态获取,可以从request里获取,
CookieUtils.setUpCookie(response, Constants.User.COOKIE_TOKE_KEY, tokenKey);
//生成refreshToken
String refreshTokenValue = JwtUtil.createRefreshToken(userFromDb.getId(), Constants.TimeValue.MONTH);
//保存到数据库里
//refreshToken,tokenKey,用户ID,创建时间,更新时间
RefreshToken refreshToken = new RefreshToken();
refreshToken.setId(idWorker.nextId() + "");
refreshToken.setRefreshToken(refreshTokenValue);
refreshToken.setUserId(userFromDb.getId());
refreshToken.setTokenKey(tokenKey);
refreshToken.setCreateTime(new Date());
refreshToken.setUpdateTime(new Date());
refreshTokenDao.save(refreshToken);
return tokenKey;
}