|
@@ -1,6 +1,7 @@
|
|
|
package com.citu.module.menduner.system.service.auth;
|
|
|
|
|
|
import cn.hutool.core.lang.Assert;
|
|
|
+import cn.hutool.core.util.IdUtil;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
|
|
|
import com.citu.framework.common.enums.TerminalEnum;
|
|
@@ -9,9 +10,11 @@ import com.citu.framework.common.pojo.CommonResult;
|
|
|
import com.citu.framework.common.util.monitor.TracerUtils;
|
|
|
import com.citu.framework.common.util.servlet.ServletUtils;
|
|
|
import com.citu.framework.common.util.validation.ValidationUtils;
|
|
|
+import com.citu.framework.security.core.LoginUser;
|
|
|
import com.citu.module.menduner.common.enums.EventAsyncUrlEnum;
|
|
|
import com.citu.module.menduner.common.enums.PointBizTypeEnum;
|
|
|
import com.citu.module.menduner.common.message.EventAsyncConfirmMessage;
|
|
|
+import com.citu.module.menduner.common.util.LoginUserContext;
|
|
|
import com.citu.module.menduner.system.controller.app.common.auth.vo.*;
|
|
|
import com.citu.module.menduner.system.controller.app.jobhunt.user.vo.AppMdeUserResetPasswordReqVO;
|
|
|
import com.citu.module.menduner.system.controller.base.logger.LoginLogCreateReqDTO;
|
|
@@ -30,6 +33,7 @@ import com.citu.module.system.api.social.SocialUserApi;
|
|
|
import com.citu.module.system.api.social.dto.SocialUserBindReqDTO;
|
|
|
import com.citu.module.system.api.social.dto.SocialUserRespDTO;
|
|
|
import com.citu.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO;
|
|
|
+import com.citu.module.system.api.social.dto.SocialWxQrcodeReqDTO;
|
|
|
import com.citu.module.system.enums.logger.LoginLogTypeEnum;
|
|
|
import com.citu.module.system.enums.logger.LoginResultEnum;
|
|
|
import com.citu.module.system.enums.oauth2.OAuth2ClientConstants;
|
|
@@ -40,8 +44,11 @@ import com.xingyuv.captcha.model.common.ResponseModel;
|
|
|
import com.xingyuv.captcha.model.vo.CaptchaVO;
|
|
|
import com.xingyuv.captcha.service.CaptchaService;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.context.annotation.Lazy;
|
|
|
+import org.springframework.data.redis.connection.StringRedisConnection;
|
|
|
+import org.springframework.data.redis.core.RedisCallback;
|
|
|
import org.springframework.data.redis.core.RedisTemplate;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
@@ -97,6 +104,9 @@ public class MdeAuthServiceImpl implements MdeAuthService {
|
|
|
@Lazy
|
|
|
private RedisTemplate<String, String> redisTemplate;
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
@VisibleForTesting
|
|
|
protected void validateCaptcha(AppMdeAuthLoginReqVO reqVO) {
|
|
|
// 如果验证码关闭,则不进行校验
|
|
@@ -444,6 +454,112 @@ public class MdeAuthServiceImpl implements MdeAuthService {
|
|
|
userService.enable(Collections.singletonList(user.getId()));
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public byte[] weixinLoginQrcode(AppMdeWeixinLoginQrcodeReqVo reqVo, String clientIP) {
|
|
|
+ String uuid = IdUtil.fastSimpleUUID();
|
|
|
+
|
|
|
+ SocialWxQrcodeReqDTO reqDTO =new SocialWxQrcodeReqDTO();
|
|
|
+ reqDTO.setScene(uuid);
|
|
|
+ reqDTO.setApplication(reqVo.getApplication());
|
|
|
+ reqDTO.setUserType(reqVo.getUserType());
|
|
|
+ reqDTO.setPath("pagesB/websiteLoginVerification/index");
|
|
|
+ long exTime = 1000L*60L*5L;
|
|
|
+
|
|
|
+ // 使用 execute 方法确保原子性
|
|
|
+ Long increment = redisTemplate.execute((RedisCallback<Long>) connection -> {
|
|
|
+ // 增加计数器
|
|
|
+ Long incr = connection.incr(String.format(MDE_WXAPP_QRCOE_CACHE_NUM, clientIP).getBytes());
|
|
|
+ // 设置过期时间
|
|
|
+ connection.expire(String.format(MDE_WXAPP_QRCOE_CACHE_NUM, clientIP).getBytes(), exTime / 1000); // 过期时间单位为秒
|
|
|
+ return incr;
|
|
|
+ });
|
|
|
+
|
|
|
+ if(null!=increment && increment>20){
|
|
|
+ throw exception(MDE_WX_APP_QRCODE_TOO_MANY);
|
|
|
+ }
|
|
|
+ // 清理 上一次获取到的 验证码信息
|
|
|
+ String s = redisTemplate.opsForValue().get(String.format(MDE_WXAPP_QRCOE, clientIP, reqVo.getClientId()));
|
|
|
+ redisTemplate.delete(String.format(MDE_WXAPP_QRCOE,clientIP,reqVo.getClientId()));
|
|
|
+ if(StringUtils.isNotBlank(s)){
|
|
|
+ redisTemplate.delete(String.format(MDE_WXAPP_QRCOE_AUTHORIZE,s));
|
|
|
+ }
|
|
|
+
|
|
|
+ redisTemplate.opsForValue().set(String.format(MDE_WXAPP_QRCOE,clientIP,reqVo.getClientId()), uuid,exTime, TimeUnit.MILLISECONDS);
|
|
|
+ redisTemplate.opsForValue().set(String.format(MDE_WXAPP_QRCOE_AUTHORIZE,uuid), "wait",exTime, TimeUnit.MILLISECONDS);
|
|
|
+ return socialClientApi.getWxaQrcode(reqDTO).getCheckedData();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void weixinLoginAuthorize(AppMdeWeixinLoginAuthorize request) {
|
|
|
+ String s = redisTemplate.opsForValue().get(String.format(MDE_WXAPP_QRCOE_AUTHORIZE, request.getUuid()));
|
|
|
+ if(StringUtils.isBlank(s)){
|
|
|
+ throw exception(MDE_WX_APP_QRCODE_EX_TIME);
|
|
|
+ }
|
|
|
+ LoginUser loginUser = LoginUserContext.get();
|
|
|
+ redisTemplate.opsForValue().set(String.format(MDE_WXAPP_QRCOE_AUTHORIZE, request.getUuid()), loginUser.getId().toString(),1000L*60L*5L, TimeUnit.MILLISECONDS);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public AppMdeWXAppAuthLoginRespVO weixinLoginAuthorizeCode(AppMdeWeixinLoginQrcodeClientIdReqVo reqVo, String clientIP) throws InterruptedException {
|
|
|
+ String uuid = redisTemplate.opsForValue().get(String.format(MDE_WXAPP_QRCOE, clientIP, reqVo.getClientId()));
|
|
|
+ if (StringUtils.isBlank(uuid)) {
|
|
|
+ throw exception(MDE_WX_APP_QRCODE_EX_TIME);
|
|
|
+ }
|
|
|
+
|
|
|
+ int checkSleep = 200;
|
|
|
+ int checkCount =200;
|
|
|
+ int checkExtime = 100+(checkCount*checkSleep);
|
|
|
+ // 使用 execute 方法确保原子性
|
|
|
+ Long increment = redisTemplate.execute((RedisCallback<Long>) connection -> {
|
|
|
+ // 增加计数器
|
|
|
+ Long incr = connection.incr(String.format(MDE_WXAPP_QRCOE_CHECK, clientIP, reqVo.getClientId()).getBytes());
|
|
|
+ // 设置过期时间
|
|
|
+ connection.expire(String.format(MDE_WXAPP_QRCOE_CHECK, clientIP, reqVo.getClientId()).getBytes(), checkExtime / 1000); // 过期时间单位为秒
|
|
|
+ return incr;
|
|
|
+ });
|
|
|
+
|
|
|
+ redisTemplate.expire(String.format(MDE_WXAPP_QRCOE_CHECK, clientIP, reqVo.getClientId()), 1000L*60L, TimeUnit.MILLISECONDS);
|
|
|
+ if(!Long.valueOf(1).equals(increment)){
|
|
|
+ throw exception(MDE_WX_APP_QRCODE_CHECK_STATE);
|
|
|
+ }
|
|
|
+ AppMdeWXAppAuthLoginRespVO appMdeWXAppAuthLoginRespVO =new AppMdeWXAppAuthLoginRespVO();
|
|
|
+
|
|
|
+ String userId = null;
|
|
|
+ for (int i=0;i<=checkCount;i++){
|
|
|
+ userId = redisTemplate.opsForValue().get(String.format(MDE_WXAPP_QRCOE_AUTHORIZE, uuid));
|
|
|
+ if(StringUtils.isNotBlank(userId) && !"wait".equals(userId)){
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ // 等待下次检查
|
|
|
+ Thread.sleep(checkSleep);
|
|
|
+ }
|
|
|
+ if(StringUtils.isBlank(userId) || "wait".equals(userId)){
|
|
|
+ // TODO 考虑返回新的clientId以保证安全性
|
|
|
+ // 使用 execute 方法确保原子性
|
|
|
+ long exTime = 1000L*60L*5L;
|
|
|
+ String newClientId = IdUtil.fastSimpleUUID();
|
|
|
+ redisTemplate.opsForValue().set(String.format(MDE_WXAPP_QRCOE,clientIP,newClientId), uuid, exTime, TimeUnit.MILLISECONDS);
|
|
|
+ redisTemplate.delete(String.format(MDE_WXAPP_QRCOE,clientIP,reqVo.getClientId()));
|
|
|
+ redisTemplate.delete(String.format(MDE_WXAPP_QRCOE_CHECK, clientIP, reqVo.getClientId()));
|
|
|
+ appMdeWXAppAuthLoginRespVO.setStatus(0);
|
|
|
+ appMdeWXAppAuthLoginRespVO.setClientId(newClientId);
|
|
|
+ return appMdeWXAppAuthLoginRespVO;
|
|
|
+ }
|
|
|
+ // 获得获得注册用户
|
|
|
+ MdeUserDO user = userService.getMdeUser(Long.valueOf(userId));
|
|
|
+ // 是否禁用
|
|
|
+ if (ObjectUtil.notEqual(user.getStatus(), MendunerStatusEnum.ENABLE.getStatus())) {
|
|
|
+ createLoginLog(user, user.getPhone(), LoginLogTypeEnum.LOGIN_WX_APP_AUTHORIZE, LoginResultEnum.USER_DISABLED);
|
|
|
+ throw exception(MDE_AUTH_LOGIN_USER_DISABLED);
|
|
|
+ } // 创建 Token 令牌,记录登录日志
|
|
|
+
|
|
|
+ appMdeWXAppAuthLoginRespVO.setAppMdeAuthLoginRespVO(createTokenAfterLoginSuccess(user, user.getPhone(), LoginLogTypeEnum.LOGIN_WX_APP_AUTHORIZE, null));
|
|
|
+ appMdeWXAppAuthLoginRespVO.setStatus(1);
|
|
|
+
|
|
|
+ return appMdeWXAppAuthLoginRespVO;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
@Override
|
|
|
public void validateSmsCode(AppMdeAuthSmsValidateReqVO reqVO) {
|
|
|
smsCodeApi.validateSmsCode(MdeAuthConvert.INSTANCE.convert(reqVO).setMobile(reqVO.getPhone())).getCheckedData();
|