123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- package com.backendsys.modules.app.service.impl;
- import cn.hutool.core.convert.Convert;
- import cn.hutool.core.date.DateUnit;
- import cn.hutool.core.date.DateUtil;
- import cn.hutool.json.JSONUtil;
- import com.backendsys.exception.CustException;
- import com.backendsys.modules.app.dao.AppUserDao;
- import com.backendsys.modules.app.entity.AppAuth;
- import com.backendsys.modules.app.entity.AppUser;
- import com.backendsys.modules.app.service.AppAuthService;
- import com.backendsys.modules.common.config.redis.utils.RedisUtil;
- import com.backendsys.modules.common.config.security.entity.SecurityAppUserInfo;
- import com.backendsys.modules.common.config.security.utils.*;
- import com.backendsys.modules.system.entity.TokenCatch;
- import com.backendsys.modules.system.service.SysCommonService;
- import com.backendsys.utils.response.ResultEnum;
- import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
- import org.springframework.stereotype.Service;
- import java.util.Date;
- import java.util.UUID;
- import java.util.concurrent.TimeUnit;
- @Service
- public class AppAuthServiceImpl implements AppAuthService {
- @Autowired
- private JwtUtil jwtUtil;
- @Autowired
- private TokenUtil tokenUtil;
- @Autowired
- private RedisUtil redisUtil;
- @Autowired
- private CaptchaUtil captchaUtil;
- @Autowired
- private LockStatusUtil lockStatusUtil;
- @Autowired
- private HttpRequestUtil httpRequestUtil;
- @Autowired
- private AppUserDao appUserDao;
- @Autowired
- private SysCommonService sysCommonService;
- @Value("${tencent.sms.debug}")
- private String SMS_DEBUG;
- @Value("${CAPTCHA_DURATION}")
- private Integer CAPTCHA_DURATION;
- @Value("${REDIS_LOGIN_TOKEN_PREFIX}")
- private String REDIS_LOGIN_TOKEN_PREFIX;
- @Value("${spring.application.name}")
- private String APPLICATION_NAME;
- private String redisKeyOfLogin = APPLICATION_NAME + "-app-sms-login";
- private String redisKeyOfRegister = APPLICATION_NAME + "-app-sms-register";
- private String redisKeyOfLoginFail = APPLICATION_NAME + "-app-login-error";
- private String redisKeyOfRegisterFail = APPLICATION_NAME + "-app-register-error";
- // [方法] 登录失败 (errMsg: 错误提示文本, phone: 手机号码, intercept: 是否拦截)
- private void loginFail(String errMsg, String phone, Boolean isIntercept) {
- // 删除图形验证码
- redisUtil.delete(httpRequestUtil.getKaptchaKey());
- // 添加登录错误的冻结标记
- if (isIntercept) lockStatusUtil.setLockStatus(redisKeyOfLoginFail, phone);
- throw new CustException(errMsg, ResultEnum.INVALID_CREDENTIALS.getCode());
- }
- // [方法] 登录成功
- private AppUser loginSuccess(AppUser appUser) {
- // 删除图形验证码缓存
- redisUtil.delete(httpRequestUtil.getKaptchaKey());
- // 删除旧的登录缓存
- tokenUtil.deleteRedisLoginToken(appUser.getLast_login_uuid());
- // 判断用户是否启用
- Integer status = appUser.getStatus();
- if (status != null && status.equals(-1)) throw new CustException("该用户已被禁用,请与客服联系");
- // 判断用户是否已删除
- Integer del_flag = appUser.getDel_flag();
- if (del_flag != null && del_flag.equals(1)) throw new CustException("当前用户不可用,请与客服联系");
- // 设置 最后一次的登录信息 (uuid, ip, 登录时间)
- String uuid = Convert.toStr(UUID.randomUUID());
- appUser.setUser_id(appUser.getId());
- appUser.setLast_login_uuid(uuid);
- appUser.setLast_login_ip(httpRequestUtil.getIpAddr());
- appUser.setLast_login_time(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
- appUserDao.updateById(appUser);
- // [系统配置] 微信用户默认登录过期时间(小时)
- Integer APP_USER_LOGIN_DURATION_DEFAULT = Convert.toInt(sysCommonService.getCommonByTag("APP_USER_LOGIN_DURATION_DEFAULT"));
- // 将小时转换为毫秒
- Long DEFAULT_MILLISECONDS = APP_USER_LOGIN_DURATION_DEFAULT * DateUnit.HOUR.getMillis();
- Integer token_duration_hours = Convert.toInt(DEFAULT_MILLISECONDS / 3600000L);
- Date token_expiration = new Date((new Date()).getTime() + DEFAULT_MILLISECONDS);
- appUser.setToken_expiration(DateUtil.format(token_expiration, "yyyy-MM-dd HH:mm:ss"));
- appUser.setRole("APP_USER");
- // 生成 Token
- SecurityAppUserInfo securityUserInfo = JSONUtil.toBean(JSONUtil.parseObj(appUser), SecurityAppUserInfo.class);
- String token = jwtUtil.createAppJwtToken(securityUserInfo);
- String token_redis_key = REDIS_LOGIN_TOKEN_PREFIX + uuid;
- appUser.setToken(token);
- // [Redis] 将 Token 存入缓存
- TokenCatch tokenCatch = new TokenCatch(token, null);
- redisUtil.setCacheObject(token_redis_key, JSONUtil.toJsonStr(tokenCatch), token_duration_hours, TimeUnit.HOURS);
- return appUser;
- }
- /**
- * APP登录 (用户名登录)
- */
- @Override
- public AppUser login(AppAuth appAuth) {
- String phone = appAuth.getPhone();
- String password = appAuth.getPassword();
- String captcha = appAuth.getCaptcha();
- // 判断是否处于登录错误的冻结状态 (2分钟内错误5次,则出现冻结提示)
- lockStatusUtil.checkLockStatus(redisKeyOfLoginFail, phone);
- // 判断图形验证码是否正确
- if (!captchaUtil.isCaptchaValid(captcha, httpRequestUtil.getKaptchaKey())) {
- loginFail("验证码错误", phone, false);
- return null;
- }
- // [Method] 判断 用户 是否存在 && 密码是否正确
- AppUser appUser = appUserDao.selectOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getPhone, phone));
- if (appUser == null) {
- // [登录失败] 用户不存在
- loginFail("手机号码或密码错误", phone, true);
- return null;
- } else {
- // [登录失败] 密码不正确
- BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
- if (!encoder.matches(password, appUser.getPassword())) {
- loginFail("手机号码或密码错误", phone, true);
- }
- // [登录成功]
- return loginSuccess(appUser);
- }
- }
- }
|