AbstractLoginService.java 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. package com.ytpm.handle;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.util.IdUtil;
  4. import cn.hutool.core.util.RandomUtil;
  5. import cn.hutool.core.util.StrUtil;
  6. import com.ytpm.agent.enums.UserStatusEnum;
  7. import com.ytpm.app.enums.LoginType;
  8. import com.ytpm.app.model.YtDyzLoginRecord;
  9. import com.ytpm.app.model.YtDyzUser;
  10. import com.ytpm.app.param.LoginParam;
  11. import com.ytpm.app.view.WxDefaultConfig;
  12. import com.ytpm.general.Result;
  13. import com.ytpm.util.IPUtil;
  14. import org.springframework.beans.factory.annotation.Value;
  15. import org.springframework.util.CollectionUtils;
  16. import javax.servlet.http.HttpServletRequest;
  17. import java.util.Date;
  18. import java.util.HashMap;
  19. import java.util.List;
  20. import java.util.Objects;
  21. import java.util.Map;
  22. /**
  23. * <p>登陆模板</p>
  24. * 兼容多登陆模式及风控校验
  25. * <p>需重写方法:<br>
  26. * 1.登陆参数校验 validateParams
  27. * 2.根据设备及渠道ID查询用户 queryUserByDeviceAndDitch
  28. * 3.获取登陆默认配置 getLoginConfig
  29. * 4.根据登陆参数获取系统用户 queryDyzUserByParam
  30. * 5.用户新注册逻辑 registryUser
  31. * 6.已注册用户处理逻辑 deadWithUserCrud
  32. * 7.登陆记录保存 saveLoginRecord
  33. * 8.远程调用风控 remoteCheckLoginRisk
  34. * 9.远程调用风控 remoteCheckRegRisk
  35. * </p>
  36. *
  37. * <p>回调方法:<br>
  38. * 1.用户注册时回调 beforeRegistryUser<br>
  39. * 2.用户登陆时回调 beforeDeadWithUserCrud
  40. * </p>
  41. *
  42. * <p>可选重写方法:<br>
  43. * 1.第三方登陆调用处理及参数传递 setThirdPartyLoginInfo <br>
  44. * 2.登陆成功后调用风控服务校验 ytRiskValidate
  45. * 3.登陆用户信息配置额外信息 setExtInfo
  46. * </p>
  47. *
  48. * @author lih
  49. * @date 2025/9/4
  50. */
  51. public abstract class AbstractLoginService {
  52. @Value("${risk.config.banned.tips}")
  53. private String tips;
  54. protected abstract LoginType getLoginType();
  55. /**
  56. * 登陆逻辑处理
  57. * @param loginParam 登陆参数
  58. * @param request request
  59. * @return YtDyzUser
  60. */
  61. public final YtDyzUser loginHandle(LoginParam loginParam, HttpServletRequest request) {
  62. loginParam.setLoginIp(IPUtil.getClientIp(request));
  63. // 获取默认配置
  64. WxDefaultConfig defaultConfig = getLoginConfig(loginParam.getAppType());
  65. if (Objects.isNull(defaultConfig)) {
  66. throw new CommonException(StrUtil.format("{}登录失败,未找到相应配置!", getLoginType().getTypeName()));
  67. }
  68. loginParam.setAppId(defaultConfig.getPlatformAppId());
  69. // 参数校验
  70. validateParams(loginParam, request);
  71. // 获取第三方登陆信息 如微信授权码、微信登陆后授权信息
  72. Map<String, Object> paramMap = setThirdPartyLoginInfo(loginParam, defaultConfig, request);
  73. YtDyzUser ytDyzUser;
  74. if (getLoginType() == LoginType.VISITOR) {
  75. // 游客模式
  76. paramMap.put("defaultConfig", defaultConfig);
  77. ytDyzUser = visitorLoginHandle(loginParam, paramMap);
  78. } else {
  79. ytDyzUser = clientLoginHandle(loginParam, paramMap);
  80. }
  81. // 配置额外信息
  82. setExtInfo(ytDyzUser, paramMap);
  83. // 添加用户登录记录
  84. addLoginRecord(loginParam,ytDyzUser.getUserId());
  85. // 调用风控服务校验默认风控配置
  86. ytRiskValidate(ytDyzUser);
  87. return ytDyzUser;
  88. }
  89. /**
  90. * 登陆参数校验
  91. */
  92. protected abstract void validateParams(LoginParam loginParam, HttpServletRequest request);
  93. /**
  94. * 微信端/IOS端登陆
  95. */
  96. private YtDyzUser clientLoginHandle(LoginParam loginParam, Map<String, Object> paramMap) {
  97. YtDyzUser ytDyzUser;
  98. List<YtDyzUser> ytDyzUsers = queryDyzUserByParam(loginParam, paramMap);
  99. if (CollectionUtils.isEmpty(ytDyzUsers)) {
  100. beforeRegistryUser(loginParam, paramMap);
  101. ytDyzUser = new YtDyzUser();
  102. registryUser(loginParam, ytDyzUser, paramMap);
  103. } else {
  104. ytDyzUser = ytDyzUsers.get(0);
  105. beforeDeadWithUserCrud(loginParam, ytDyzUser, paramMap);
  106. deadWithUserCrud(loginParam, ytDyzUser, paramMap);
  107. }
  108. return ytDyzUser;
  109. }
  110. /**
  111. * 游客模式登录
  112. */
  113. private YtDyzUser visitorLoginHandle(LoginParam loginParam, Map<String, Object> paramMap) {
  114. // 唯一性判断
  115. // 1.查询设备ID不存在记录 则根据设备id+渠道id注册用户
  116. // 2.查询设备ID存在记录 则根据渠道ID控制唯一性,同步出路风控记录
  117. YtDyzUser ytDyzUser = null;
  118. List<YtDyzUser> ytDyzUsers = queryDyzUserByParam(loginParam, paramMap);
  119. if(CollUtil.isEmpty(ytDyzUsers)) {
  120. //注册后回调
  121. beforeRegistryUser(loginParam, paramMap);
  122. ytDyzUser = new YtDyzUser();
  123. registryUser(loginParam, ytDyzUser, paramMap);
  124. } else {
  125. // 查询当前设备当前渠道是否存在该用户
  126. ytDyzUser = queryUserByDeviceAndDitch(loginParam.getDeviceId(), loginParam.getDitchId());
  127. if(ytDyzUser == null) {
  128. ytDyzUser = new YtDyzUser();
  129. registryUser(loginParam, ytDyzUser, paramMap);
  130. }
  131. //当前渠道已有用户,校验用户是否处于风控中 & 更新用户信息
  132. beforeDeadWithUserCrud(loginParam, ytDyzUser, paramMap);
  133. //如果当前登录是本日第一次登录则登录天数+1
  134. deadWithUserCrud(loginParam, ytDyzUser, paramMap);
  135. }
  136. // 保存广告信息
  137. WxDefaultConfig defaultConfig = (WxDefaultConfig) paramMap.get("defaultConfig");
  138. saveVisitorAdRecord(ytDyzUser, loginParam, defaultConfig);
  139. return ytDyzUser;
  140. }
  141. // 游客登陆时保存传递记录
  142. protected void saveVisitorAdRecord(YtDyzUser ytDyzUser, LoginParam loginParam, WxDefaultConfig defaultConfig) {
  143. }
  144. /**
  145. * 根据设备及渠道ID查询用户
  146. */
  147. protected abstract YtDyzUser queryUserByDeviceAndDitch(String deviceId, Long ditchId);
  148. /**
  149. * 第三方登陆调用处理及参数传递
  150. */
  151. protected Map<String, Object> setThirdPartyLoginInfo(LoginParam loginParam, WxDefaultConfig defaultConfig,
  152. HttpServletRequest request) {
  153. Map<String, Object> map = new HashMap<>();
  154. return map;
  155. }
  156. /**
  157. * 获取登陆默认配置
  158. */
  159. protected abstract WxDefaultConfig getLoginConfig(Integer appType);
  160. /**
  161. * 根据登陆配置信息 查询系统用户记录
  162. * @param loginParam 登陆参数
  163. * @param thirdPartyLoginInfo 第三方登陆西悉尼
  164. */
  165. protected abstract List<YtDyzUser> queryDyzUserByParam(LoginParam loginParam, Map<String, Object> thirdPartyLoginInfo);
  166. // 注册用户处理器回调
  167. protected void beforeRegistryUser(LoginParam loginParam, Map<String, Object> paramMap){
  168. }
  169. // 用户注册逻辑
  170. protected abstract YtDyzUser registryUser(LoginParam loginParam,YtDyzUser user, Map<String, Object> paramMap);
  171. // 已注册用户处理前回调
  172. protected void beforeDeadWithUserCrud(LoginParam loginParam, YtDyzUser ytDyzUser, Map<String, Object> paramMap){
  173. //当前渠道已有用户,校验用户是否处于风控中 & 更新用户信息
  174. if(ytDyzUser != null && !ytDyzUser.getUserStatus().equals(UserStatusEnum.NORMAL.getCode())){
  175. throw new CommonException(getTipsMsg());
  176. }
  177. }
  178. private String getTipsMsg(){
  179. String[] split = tips.split(",");
  180. return split[RandomUtil.randomInt(split.length)];
  181. }
  182. // 已注册用户处理逻辑
  183. protected abstract void deadWithUserCrud(LoginParam loginParam, YtDyzUser old, Map<String, Object> paramMap);
  184. private void addLoginRecord(LoginParam param, String userId) {
  185. YtDyzLoginRecord loginRecord = new YtDyzLoginRecord();
  186. loginRecord.setRecordId(IdUtil.fastSimpleUUID());
  187. loginRecord.setUserId(userId);
  188. loginRecord.setLoginTime(new Date());
  189. loginRecord.setDeviceBrand(param.getBrand());
  190. loginRecord.setDeviceModel(param.getModel());
  191. loginRecord.setLoginIp(param.getLoginIp());
  192. loginRecord.setOperator(param.getIpOperator());
  193. loginRecord.setIpAddr(param.getIpLocation());
  194. loginRecord.setPhoneJson(param.getPhoneJson());
  195. saveLoginRecord(loginRecord);
  196. }
  197. /**
  198. * 保存登陆记录实现
  199. */
  200. protected abstract void saveLoginRecord(YtDyzLoginRecord loginRecord);
  201. /**
  202. * 调用风控服务校验默认风控配置
  203. */
  204. protected void ytRiskValidate(YtDyzUser ytDyzUser) {
  205. Result<?> result = remoteCheckLoginRisk(ytDyzUser);
  206. if (result == null || result.getCode() != 200) {
  207. throw new CommonException(result == null ? "feign invoke Fail!" : result.getMessage());
  208. }
  209. }
  210. /**
  211. * 配置相关信息
  212. *
  213. * @param ytDyzUser
  214. * @param paramMap
  215. */
  216. protected void setExtInfo(YtDyzUser ytDyzUser, Map<String, Object> paramMap) {
  217. }
  218. /**
  219. * 远程调用校验用户风控,需设置风控编码[riskCode],并重写该方法
  220. * @param ytDyzUser 当前用户
  221. */
  222. protected abstract Result<?> remoteCheckLoginRisk(YtDyzUser ytDyzUser);
  223. /**
  224. * 远程调用校验注册用户
  225. * @param user 参数
  226. */
  227. protected abstract Result<?> remoteCheckRegRisk(YtDyzUser user);
  228. }