diff --git a/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/annotation/MaskResponse.java b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/annotation/MaskResponse.java new file mode 100644 index 0000000000..1cbbd2a887 --- /dev/null +++ b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/annotation/MaskResponse.java @@ -0,0 +1,44 @@ +package com.epmet.commons.tools.annotation; + +import com.epmet.commons.tools.enums.RequirePermissionEnum; +import javassist.runtime.Inner; + +import java.lang.annotation.*; +import java.util.function.Function; + +/** + * 标记一个接口,它的返回值中的某些字段需要打掩码 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface MaskResponse { + + /** + * 掩码类型 + */ + String MASK_TYPE_ID_CARD = "ID_CARD"; + String MASK_TYPE_MOBILE = "MOBILE"; + + ///** + // * 默认的一些字段,如果没有手动指定,就会使用默认的。如果手动指定了,就不再使用默认的 + // */ + //String[] defaultFieldnames = {"idCard","mobile","phone"}; + // + ///** + // * 默认字段对应的掩码类型 + // */ + //String[] defaultFieldsMaskType = { MASK_TYPE_ID_CARD, MASK_TYPE_MOBILE, MASK_TYPE_MOBILE }; + + /** + * 要打码的字段列表。会递归的着这些字段 + * @return + */ + String[] fieldNames() default {"idCard","mobile","phone"}; + + /** + * 要打码的类型 + * @return + */ + String[] fieldsMaskType() default { MASK_TYPE_ID_CARD, MASK_TYPE_MOBILE, MASK_TYPE_MOBILE }; +} diff --git a/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/aspect/MaskResponseAspect.java b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/aspect/MaskResponseAspect.java new file mode 100644 index 0000000000..c3883c45b0 --- /dev/null +++ b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/aspect/MaskResponseAspect.java @@ -0,0 +1,36 @@ +package com.epmet.commons.tools.aspect; + +import com.epmet.commons.tools.annotation.MaskResponse; +import com.epmet.commons.tools.exception.EpmetErrorCode; +import com.epmet.commons.tools.exception.EpmetException; +import com.epmet.commons.tools.processor.MaskProcessor; +import com.epmet.commons.tools.utils.Result; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@Aspect +@Component +@Order(0) +public class MaskResponseAspect { + + @AfterReturning(pointcut = "@annotation(com.epmet.commons.tools.annotation.MaskResponse)", returning = "result") + public Object proceed(JoinPoint point, Result result) throws Throwable { + MethodSignature signature = (MethodSignature) point.getSignature(); + MaskResponse maskResponseAnno = signature.getMethod().getAnnotation(MaskResponse.class); + + String[] fieldNames = maskResponseAnno.fieldNames(); + String[] fieldsMaskType = maskResponseAnno.fieldsMaskType(); + + if (fieldNames.length != fieldsMaskType.length) { + String msg = "掩码配置错误"; + throw new EpmetException(EpmetErrorCode.SERVER_ERROR.getCode(), msg, msg); + } + + new MaskProcessor(fieldNames, fieldsMaskType).mask(result); + return null; + } +} diff --git a/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/processor/MaskProcessor.java b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/processor/MaskProcessor.java new file mode 100644 index 0000000000..266acfdcbc --- /dev/null +++ b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/processor/MaskProcessor.java @@ -0,0 +1,142 @@ +package com.epmet.commons.tools.processor; + +import cn.hutool.core.util.StrUtil; +import com.epmet.commons.tools.annotation.MaskResponse; +import com.epmet.commons.tools.exception.ExceptionUtils; +import com.epmet.commons.tools.page.PageData; +import com.epmet.commons.tools.utils.Result; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +@Slf4j +public class MaskProcessor { + + + public static final String EPMET_PACKAGE_PREFIX = "com.epmet"; + + private List fieldNames; + private List fieldsMaskType; + + public MaskProcessor(String[] fields, String[] fieldsMaskType) { + if (fields != null && fields.length > 0) { + this.fieldNames = Arrays.asList(fields); + this.fieldsMaskType = Arrays.asList(fieldsMaskType); + } + } + + /** + * 为dto中的属性打掩码 + * @param object + */ + public void mask(Object object) { + if (object == null) { + return; + } + + if (object instanceof Result) { + mask(((Result) object).getData()); + return; + } else if (object instanceof PageData) { + mask(((PageData) object).getList()); + return; + } else if (object instanceof List) { + ((List)object).forEach(e -> mask(e)); + return; + } else if (object instanceof Map) { + ((Map) object).values().forEach(v -> mask(v)); + return; + } else if (object.getClass().getName().startsWith(EPMET_PACKAGE_PREFIX)) { + // 自定义bean,走反射 + maskEpmetBean(object); + } + } + + /** + * 反射 + * @param object + */ + private void maskEpmetBean(Object object) { + Field[] declaredFields = object.getClass().getDeclaredFields(); + for (Field currentField : declaredFields) { + currentField.setAccessible(true); + try { + String fieldName = currentField.getName(); + Object value = currentField.get(object); + // 是epmet的类,继续下钻 + if (currentField.getClass().getName().startsWith(EPMET_PACKAGE_PREFIX)) { + maskEpmetBean(value); + continue; + } + + // 是字符串 + String fieldValue; + if (value instanceof String && StringUtils.isNotBlank(fieldValue = (String) value)) { + int fieldIndexInAnnoAttrs = fieldNames.indexOf(fieldName); + if (fieldIndexInAnnoAttrs != -1) { + String product = maskString(fieldValue, fieldsMaskType.get(fieldIndexInAnnoAttrs)); + currentField.set(object, product); + } + continue; + } + + // 非字符串,非epmet类的其他类型 + mask(value); + } catch (IllegalAccessException e) { + log.error("【mask一些字段报错】{}", ExceptionUtils.getErrorStackTrace(e)); + } + } + } + + /** + * 把字符串变更为掩码 + * @param originString + * @return + */ + public String maskString(String originString, String maskType) { + if (MaskResponse.MASK_TYPE_ID_CARD.equals(maskType)) { + return maskIdCard(originString); + } else if (MaskResponse.MASK_TYPE_MOBILE.equals(maskType)) { + return maskMobile(originString); + } else { + return originString; + } + } + + /** + * 将明文字符串打码变为掩码。保留前6,后面打码 + * @param originString + * @return + */ + private String maskIdCard(String originString) { + // 仅将6位之后的全都打码 + int length = originString.length(); + if (length <= 6) { + return originString; + } + + return originString.replace(originString.substring(6), StrUtil.repeatByLength("*", length - 6)); + } + + /** + * 将明文字符串打码变为掩码。保留前3后4,中间打码 + * 187****3461 + * @param originString + * @return + */ + private String maskMobile(String originString) { + int length = originString.length(); + if (length <= 7) { + return originString; + } + + String maskStr = StrUtil.repeatByLength("*", length - 7); + + return originString.replaceAll("^(1\\d{2})\\d*(\\d{4})$", new StringBuilder("$1").append(maskStr).append("$2").toString()); + } +} diff --git a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/aspect/RequestLogAspect.java b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/aspect/RequestLogAspect.java index 49581cf63c..f9be4267e8 100644 --- a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/aspect/RequestLogAspect.java +++ b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/aspect/RequestLogAspect.java @@ -17,7 +17,7 @@ import javax.servlet.http.HttpServletRequest; */ @Aspect @Component -@Order(0) +@Order(1) public class RequestLogAspect extends BaseRequestLogAspect { @Override diff --git a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/controller/HouseController.java b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/controller/HouseController.java index 5ef535aa11..69e3f620f8 100644 --- a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/controller/HouseController.java +++ b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/controller/HouseController.java @@ -19,6 +19,7 @@ package com.epmet.controller; import cn.afterturn.easypoi.excel.entity.TemplateExportParams; import com.epmet.commons.tools.annotation.LoginUser; +import com.epmet.commons.tools.annotation.MaskResponse; import com.epmet.commons.tools.aop.NoRepeatSubmit; import com.epmet.commons.tools.constant.NumConstant; import com.epmet.commons.tools.constant.ServiceConstant; @@ -69,8 +70,9 @@ public class HouseController implements ResultDataResolver { @Autowired private EpmetCommonServiceOpenFeignClient epmetCommonServiceOpenFeignClient; - @PostMapping("houselist") + @MaskResponse(fieldNames = {"ownerIdCard", "ownerPhone"}, + fieldsMaskType = { MaskResponse.MASK_TYPE_ID_CARD, MaskResponse.MASK_TYPE_MOBILE }) public Result> houseList(@RequestBody IcHouseListFormDTO formDTO) { //效验数据 ValidatorUtils.validateEntity(formDTO); diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/aspect/RequestLogAspect.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/aspect/RequestLogAspect.java index 49581cf63c..f9be4267e8 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/aspect/RequestLogAspect.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/aspect/RequestLogAspect.java @@ -17,7 +17,7 @@ import javax.servlet.http.HttpServletRequest; */ @Aspect @Component -@Order(0) +@Order(1) public class RequestLogAspect extends BaseRequestLogAspect { @Override diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcEpidemicPreventionController.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcEpidemicPreventionController.java index c490634108..3fd2bd60fc 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcEpidemicPreventionController.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcEpidemicPreventionController.java @@ -18,6 +18,7 @@ package com.epmet.controller; import com.epmet.commons.tools.annotation.LoginUser; +import com.epmet.commons.tools.annotation.MaskResponse; import com.epmet.commons.tools.page.PageData; import com.epmet.commons.tools.security.dto.TokenDto; import com.epmet.commons.tools.utils.Result; @@ -58,6 +59,7 @@ public class IcEpidemicPreventionController{ * @Date 2022/3/29 14:25 */ @PostMapping("page") + @MaskResponse(fieldNames = { "mobile", "idCard" }, fieldsMaskType = { MaskResponse.MASK_TYPE_MOBILE, MaskResponse.MASK_TYPE_ID_CARD }) public Result> search(@LoginUser TokenDto tokenDto, @RequestBody EpidemicPreventionFormDTO formDTO) { formDTO.setCustomerId(tokenDto.getCustomerId()); formDTO.setStaffId(tokenDto.getUserId()); diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcEpidemicSpecialAttentionController.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcEpidemicSpecialAttentionController.java index b2d1ea6249..60bb98cc89 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcEpidemicSpecialAttentionController.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcEpidemicSpecialAttentionController.java @@ -2,6 +2,7 @@ package com.epmet.controller; import cn.afterturn.easypoi.excel.entity.TemplateExportParams; import com.epmet.commons.tools.annotation.LoginUser; +import com.epmet.commons.tools.annotation.MaskResponse; import com.epmet.commons.tools.aop.NoRepeatSubmit; import com.epmet.commons.tools.constant.NumConstant; import com.epmet.commons.tools.dto.form.PageFormDTO; @@ -58,6 +59,7 @@ public class IcEpidemicSpecialAttentionController { * @date 2022/3/28 10:29 */ @PostMapping("list") + @MaskResponse(fieldNames = { "mobile", "idCard" }, fieldsMaskType = { MaskResponse.MASK_TYPE_MOBILE, MaskResponse.MASK_TYPE_ID_CARD }) public Result vaccinationList(@RequestBody VaccinationListFormDTO formDTO, @LoginUser TokenDto tokenDto){ ValidatorUtils.validateEntity(formDTO, PageFormDTO.AddUserInternalGroup.class, VaccinationListFormDTO.VaccinationListForm.class); formDTO.setCustomerId(tokenDto.getCustomerId()); diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcNatController.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcNatController.java index e65121e55d..1098aa680e 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcNatController.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcNatController.java @@ -4,6 +4,7 @@ import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.write.metadata.WriteSheet; import com.epmet.commons.tools.annotation.LoginUser; +import com.epmet.commons.tools.annotation.MaskResponse; import com.epmet.commons.tools.aop.NoRepeatSubmit; import com.epmet.commons.tools.constant.AppClientConstant; import com.epmet.commons.tools.constant.NumConstant; @@ -114,6 +115,7 @@ public class IcNatController implements ResultDataResolver { **/ @NoRepeatSubmit @PostMapping("natlist") + @MaskResponse(fieldNames = { "mobile", "idCard" }, fieldsMaskType = { MaskResponse.MASK_TYPE_MOBILE, MaskResponse.MASK_TYPE_ID_CARD }) public Result> natList(@LoginUser TokenDto tokenDto, @RequestBody MyNatListFormDTO formDTO) { formDTO.setCustomerId(tokenDto.getCustomerId()); formDTO.setUserId(tokenDto.getUserId()); diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcResiCollectController.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcResiCollectController.java index c25f04bc2b..54314229cf 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcResiCollectController.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcResiCollectController.java @@ -1,6 +1,7 @@ package com.epmet.controller; import com.epmet.commons.tools.annotation.LoginUser; +import com.epmet.commons.tools.annotation.MaskResponse; import com.epmet.commons.tools.aop.NoRepeatSubmit; import com.epmet.commons.tools.constant.StrConstant; import com.epmet.commons.tools.page.PageData; @@ -71,6 +72,8 @@ public class IcResiCollectController { * @date 2022/3/18 19:23 */ @PostMapping("list") + @MaskResponse(fieldNames = { "memberIdNum", "memberMobile" }, + fieldsMaskType = { MaskResponse.MASK_TYPE_ID_CARD, MaskResponse.MASK_TYPE_MOBILE }) public Result> getCollectList(@RequestBody CollectListFormDTO formDTO, @LoginUser TokenDto tokenDto){ ValidatorUtils.validateEntity(formDTO,CollectListFormDTO.CollectListForm.class); formDTO.setUserId(tokenDto.getUserId()); diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcResiUserController.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcResiUserController.java index 5a44547fc8..c767f0b645 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcResiUserController.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcResiUserController.java @@ -23,6 +23,7 @@ import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.fill.FillWrapper; import com.epmet.commons.rocketmq.messages.IcResiUserAddMQMsg; import com.epmet.commons.tools.annotation.LoginUser; +import com.epmet.commons.tools.annotation.MaskResponse; import com.epmet.commons.tools.aop.NoRepeatSubmit; import com.epmet.commons.tools.constant.AppClientConstant; import com.epmet.commons.tools.constant.Constant; @@ -656,6 +657,7 @@ public class IcResiUserController implements ResultDataResolver { * @Date 2021/12/10 17:54 */ @PostMapping("partymemberagelist") + @MaskResponse(fieldNames = { "mobile" }, fieldsMaskType = { MaskResponse.MASK_TYPE_MOBILE }) public Result> partyMemberAgelist(@RequestBody PartyMemberListFormDTO formDTO) { ValidatorUtils.validateEntity(formDTO); return new Result>().ok(icResiUserService.getPartyMemberAgeList(formDTO)); @@ -732,6 +734,7 @@ public class IcResiUserController implements ResultDataResolver { * @Date 2021/12/10 17:58 */ @PostMapping("partymembereducationlist") + @MaskResponse(fieldNames = { "mobile" }, fieldsMaskType = { MaskResponse.MASK_TYPE_MOBILE }) public Result> partyMemberEducationlist(@RequestBody PartyMemberListFormDTO formDTO) { ValidatorUtils.validateEntity(formDTO); return new Result>().ok(icResiUserService.getPartyMemberEducationList(formDTO)); @@ -855,6 +858,7 @@ public class IcResiUserController implements ResultDataResolver { * @date 2022/1/17 4:25 下午 */ @PostMapping("personwarn/rightlist") + @MaskResponse(fieldNames = "mobile", fieldsMaskType = { MaskResponse.MASK_TYPE_MOBILE }) public Result personWarnRightList(@RequestBody PersonWarnRightListFormDTO formDTO,@LoginUser TokenDto tokenDto){ ValidatorUtils.validateEntity(formDTO, PersonWarnRightListFormDTO.PersonWarnRightListForm.class); return new Result().ok(icResiUserService.personWarnRightList(formDTO,tokenDto)); diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcTripReportRecordController.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcTripReportRecordController.java index 9bae2a9826..a023634f5e 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcTripReportRecordController.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcTripReportRecordController.java @@ -4,6 +4,7 @@ import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.write.metadata.WriteSheet; import com.epmet.commons.tools.annotation.LoginUser; +import com.epmet.commons.tools.annotation.MaskResponse; import com.epmet.commons.tools.aop.NoRepeatSubmit; import com.epmet.commons.tools.constant.AppClientConstant; import com.epmet.commons.tools.constant.NumConstant; @@ -72,6 +73,7 @@ public class IcTripReportRecordController implements ResultDataResolver { * @return */ @PostMapping("page") + @MaskResponse(fieldNames = { "mobile", "idCard" }, fieldsMaskType = { MaskResponse.MASK_TYPE_MOBILE, MaskResponse.MASK_TYPE_ID_CARD }) public Result> page(@LoginUser TokenDto tokenDto,@RequestBody PageTripReportFormDTO formDTO){ formDTO.setCustomerId(tokenDto.getCustomerId()); formDTO.setUserId(tokenDto.getUserId()); diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcVaccineController.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcVaccineController.java index 166cdecf32..07f3e9305c 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcVaccineController.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/controller/IcVaccineController.java @@ -4,6 +4,7 @@ import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.write.metadata.WriteSheet; import com.epmet.commons.tools.annotation.LoginUser; +import com.epmet.commons.tools.annotation.MaskResponse; import com.epmet.commons.tools.aop.NoRepeatSubmit; import com.epmet.commons.tools.constant.AppClientConstant; import com.epmet.commons.tools.constant.NumConstant; @@ -68,6 +69,7 @@ public class IcVaccineController implements ResultDataResolver { **/ @NoRepeatSubmit @PostMapping("vaccine-list") + @MaskResponse(fieldNames = { "mobile", "idCard" }, fieldsMaskType = { MaskResponse.MASK_TYPE_MOBILE, MaskResponse.MASK_TYPE_ID_CARD }) public Result> vaccineList(@LoginUser TokenDto tokenDto, @RequestBody VaccineListFormDTO formDTO) { formDTO.setCustomerId(tokenDto.getCustomerId()); formDTO.setUserId(tokenDto.getUserId()); diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserServiceImpl.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserServiceImpl.java index bf4e68bd1d..72eadb26c3 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserServiceImpl.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserServiceImpl.java @@ -67,12 +67,18 @@ import com.google.common.cache.CacheBuilder; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; import java.sql.Date;