记得上下班打卡 | git大法好,push需谨慎

Commit e4a49505 authored by 姜秀龙's avatar 姜秀龙

一个身份证只能绑定一个账号,100031

parent fac85886
......@@ -42,6 +42,12 @@ public class AdamRedisConst {
*/
public static final String INFO_CERTIFICATION_JUNK = PREFIX.concat("info:certification_junk:");
/**
* 身份证号 -> 已绑定实名的 uid(用于快速判重:同一身份证只能实名一个账号)
* value: uid(String)
*/
public static final String INFO_REAL_NAME_UID_BY_IDCARD = PREFIX.concat("info:real_name:uid_by_idcard:");
public static final String INFO_MEMBER_JOINUS = PREFIX.concat("info:member:joinus:");
public static final String INFO_MEMBER_SIMPLE = PREFIX.concat("info:member:simple");
public static final String INFO_MEMBER_CATEGORY = PREFIX.concat("info:member:category:");
......
......@@ -300,16 +300,15 @@ public class AdamUserController {
}
String currentUid = CurrentUtil.getCurrentUid();
AdamRealInfoVo realInfoVoByUid = adamRdmService.getRealInfoVoByUidPlain(currentUid);
// 已实名 && 三要素通过
if (null != realInfoVoByUid && realInfoVoByUid.getNode() == 3) {
// 用户输入信息与三要素通过的信息相符,则认证通过
if ((realInfoVoByUid.getName().concat(realInfoVoByUid.getIdCard())).equals(name.concat(idCard))) {
// 已实名:无论二要素(node=2)还是三要素(node=3),都视为已完成实名,直接返回(避免重复实名/跨入口重复认证)
if (null != realInfoVoByUid && realInfoVoByUid.getState() != null && realInfoVoByUid.getState() == 1) {
realInfoVoByUid.setName(SensitizeUtil.chineseName(realInfoVoByUid.getName()));
realInfoVoByUid.setIdCard(SensitizeUtil.custom(realInfoVoByUid.getIdCard(), 3, 2));
return ResponseDto.success(realInfoVoByUid);
} else {
return ResponseDto.failure(ErrorMapping.get("10113"));
}
ResponseDto<AdamRealInfoVo> guard = guardIdCardNotBoundToOtherUid(currentUid, idCard);
if (guard != null) {
return guard;
}
AdamRealInfoVo vo = adamUserService.identityForUpsert(currentUid, name, idCard, (String) CurrentUtil.getTokenClaims().get(CurrentUtil.TOKEN_MOBILE), true);
vo.setName(SensitizeUtil.chineseName(vo.getName()));
......@@ -504,7 +503,8 @@ public class AdamUserController {
return ResponseDto.failure(ErrorMapping.get("10114"));
}
AdamRealInfoVo realInfoVoByUidPlain = adamRdmService.getRealInfoVoByUidPlain(uid);
if (null == realInfoVoByUidPlain || 3 != realInfoVoByUidPlain.getNode()) {
// 已实名:兼容二要素(node=2) 与 三要素(node=3),统一以 state=1 为准
if (null == realInfoVoByUidPlain || realInfoVoByUidPlain.getState() == null || realInfoVoByUidPlain.getState() != 1) {
return ResponseDto.failure(ErrorMapping.get("10115"));
}
AdamUserIdentityInfoVo userIdentityInfoVo = AdamUserIdentityInfoVo.getNew();
......@@ -590,6 +590,10 @@ public class AdamUserController {
return ResponseDto.failure(ErrorMapping.get("10104"));
}
ResponseDto<AdamRealInfoVo> guard = guardIdCardNotBoundToOtherUid(currentUid, idCard);
if (guard != null) {
return guard;
}
AdamRealInfoVo vo = adamUserService.verifyTwoElements(currentUid, name, idCard);
if (null == vo) {
log.error("[identityV2] 二要素认证失败, param: {}", JsonUtils.toJson(param));
......@@ -601,6 +605,21 @@ public class AdamUserController {
}
/**
* 同一个身份证号(state=1)只能绑定一个账号。
* 放在 controller 层:对所有实名入口统一拦截,返回明确错误码给前端。
*/
private ResponseDto<AdamRealInfoVo> guardIdCardNotBoundToOtherUid(String uid, String idCard) {
if (StringUtils.isBlank(uid) || StringUtils.isBlank(idCard)) {
return null;
}
String boundUid = adamRdmService.getRealNameBoundUidByIdCard(idCard);
if (StringUtils.isNotBlank(boundUid) && !uid.equals(boundUid)) {
return ResponseDto.failure(ErrorMapping.get("10614"));
}
return null;
}
/* ---------------------------- Internal Method ---------------------------- */
private static final String PHP_API_SMS_CODE_VALID = "/smsValidation";
......
......@@ -2,6 +2,7 @@ package com.liquidnet.service.adam.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.databind.JsonNode;
import com.liquidnet.common.cache.redis.util.RedisDataSourceUtil;
import com.liquidnet.common.cache.redis.util.RedisUtil;
......@@ -15,12 +16,14 @@ import com.liquidnet.service.adam.dto.AdamUserInfoDto;
import com.liquidnet.service.adam.dto.vo.*;
import com.liquidnet.service.adam.entity.AdamCaomeiBadge;
import com.liquidnet.service.adam.entity.AdamEnters;
import com.liquidnet.service.adam.entity.AdamRealName;
import com.liquidnet.service.adam.entity.AdamUserMember;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinPerformanceVo;
import com.liquidnet.service.adam.mapper.AdamCaomeiBadgeMapper;
import com.liquidnet.service.adam.mapper.AdamCaomeiPassportMapper;
import com.liquidnet.service.adam.mapper.AdamEntersMapper;
import com.liquidnet.service.adam.mapper.AdamRealNameMapper;
import com.liquidnet.service.adam.mapper.AdamUserMapper;
import com.liquidnet.service.adam.mapper.AdamUserMemberMapper;
import com.liquidnet.service.adam.util.ObjectUtil;
......@@ -55,6 +58,8 @@ public class AdamRdmService {
@Autowired
AdamUserMemberMapper adamUserMemberMapper;
@Autowired
AdamRealNameMapper adamRealNameMapper;
@Autowired
AdamEntersMapper adamEntersMapper;
@Autowired
AdamCaomeiBadgeMapper adamCaomeiBadgeMapper;
......@@ -271,6 +276,50 @@ public class AdamRdmService {
redisUtil.del(AdamRedisConst.INFO_REAL_NAME.concat(uid));
}
/**
* 根据身份证号查询已实名绑定的 uid(优先 Redis,未命中回源 MySQL 并回写 Redis)
* 返回空表示未绑定或不可用。
*/
public String getRealNameBoundUidByIdCard(String idCard) {
if (StringUtils.isEmpty(idCard)) {
return "";
}
String key = AdamRedisConst.INFO_REAL_NAME_UID_BY_IDCARD.concat(idCard);
try {
String uid = (String) redisUtil.get(key);
if (!StringUtils.isEmpty(uid)) {
return uid;
}
} catch (Exception e) {
log.warn("[getRealNameBoundUidByIdCard] redis get failed, key: {}", key, e);
}
// 回源 MySQL:取任意一个 state=1 的 uid(同证件号按规则应唯一)
try {
AdamRealName r = adamRealNameMapper.selectOne(
Wrappers.lambdaQuery(AdamRealName.class)
.eq(AdamRealName::getState, 1)
.eq(AdamRealName::getType, 1)
.eq(AdamRealName::getIdCard, idCard)
.orderByDesc(AdamRealName::getMid)
.last("limit 1")
);
String uid = r != null ? org.springframework.util.StringUtils.trimWhitespace(r.getUid()) : "";
if (!StringUtils.isEmpty(uid)) {
try {
// 30天过期:防止长期脏数据无法自愈;真实解绑/注销可再补 delete
redisUtil.set(key, uid, 60L * 60 * 24 * 30);
} catch (Exception e) {
log.warn("[getRealNameBoundUidByIdCard] redis set failed, key: {}", key, e);
}
}
return uid;
} catch (Exception e) {
log.error("[getRealNameBoundUidByIdCard] mysql fallback failed, idCard: {}", idCard, e);
// 降级:查询失败直接放行(由上层决定是否继续阻断)
return "";
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | 认证失败的<ID_TYPE+ID_NO, ID_NAME> */
public boolean setCertificationJunk(int idType, String idNo, String idName) {
......
......@@ -101,6 +101,7 @@
10611=\u60A8\u6682\u65E0\u8D2D\u7968\u8BB0\u5F55\uFF0C\u8BF7\u4E0A\u4F20\u8BA2\u5355\u622A\u56FE
10612=\u7279\u6B8A\u5FBD\u7AE0\u4E0D\u53EF\u81EA\u52A9\u9886\u53D6
10613=\u672A\u77E5\u7684\u5FBD\u7AE0\u7C7B\u578B
10614=\u8BE5\u5B9E\u540D\u4FE1\u606F\u5DF2\u7ED1\u5B9A\u5176\u4ED6\u8D26\u53F7
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment