日常代码开发截图

 

接口代码

复制代码
package com.differ.jackyun.jackyunassservice.service.sensitivedataprocessv2;

import com.differ.jackyun.jackyunassbase.infrastructure.datacore.BaseContextInfo;

import java.util.List;

/**
 * 电商平台敏感数据处理方案接口。
 *
 * @Author hgw
 * @Date 2021-11-01
 */
public interface ISensitiveDataProcessV2 {
    /**
     * 数据解密
     *
     * @param contextInfo             会员名称
     * @param hasFuzzy                是否为打码输出(打码输出=true;明文输出=false)
     * @param sensitiveDataModule     解密业务模块
     * @param beSensitiveDataItemList 待解密项集合
     */
    void decrypt(BaseContextInfo contextInfo, boolean hasFuzzy, SensitiveDataModuleEnumV2 sensitiveDataModule, List<BeSensitiveDataItem> beSensitiveDataItemList);
}
View Code
复制代码

 

基类代码

复制代码
package com.differ.jackyun.jackyunassservice.service.sensitivedataprocessv2;

import com.differ.jackyun.jackyunassbase.infrastructure.datacore.BaseContextInfo;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 电商平台敏感数据处理方案(OaId解密方式)。
 *
 * @Author hgw
 * @Date 2021-11-01
 */
@Component
@Lazy(true)
public class BaseSensitiveDataProcessV2 implements ISensitiveDataProcessV2 {
    //region 变量

    //endregion

    //region ISensitiveDataProcess

    /**
     * 数据解密
     *
     * @param contextInfo             会员名称
     * @param hasFuzzy                是否为打码输出(打码输出=true;明文输出=false)
     * @param sensitiveDataModule     解密业务模块
     * @param beSensitiveDataItemList 待解密项集合
     */
    @Override
    public void decrypt(BaseContextInfo contextInfo, boolean hasFuzzy, SensitiveDataModuleEnumV2 sensitiveDataModule, List<BeSensitiveDataItem> beSensitiveDataItemList) {
        //如果没有任何解密项则直接返回。
        if (CollectionUtils.isEmpty(beSensitiveDataItemList)) {
            return;
        }

        //校验输入参数
        if (!this.validateInput(hasFuzzy, sensitiveDataModule, beSensitiveDataItemList)) {
            return;
        }

        //校验业务逻辑
        if (!this.validateBusinessLogic(hasFuzzy, sensitiveDataModule, beSensitiveDataItemList)) {
            return;
        }

        //数据解密详情方法
        this.decryptProfile(contextInfo, hasFuzzy, sensitiveDataModule, beSensitiveDataItemList);
    }

    //endregion

    //region 继承类需要重写方法

    /**
     * 数据解密详情方法。
     *
     * @param contextInfo             会员名称
     * @param hasFuzzy                是否为打码输出(打码输出=true;明文输出=false)
     * @param sensitiveDataModule     解密业务模块
     * @param beSensitiveDataItemList 待解密项集合
     */
    protected void decryptProfile(BaseContextInfo contextInfo, boolean hasFuzzy, SensitiveDataModuleEnumV2 sensitiveDataModule, List<BeSensitiveDataItem> beSensitiveDataItemList) {

    }

    /**
     * 校验输入参数。
     *
     * @param hasFuzzy                是否为打码输出(打码输出=true;明文输出=false)
     * @param sensitiveDataModule     解密业务模块
     * @param beSensitiveDataItemList 待解密项集合
     * @return 校验成功或失败(不建议直接抛出异常 , 以免影响其他数据解密)
     */
    protected boolean validateInput(boolean hasFuzzy, SensitiveDataModuleEnumV2 sensitiveDataModule, List<BeSensitiveDataItem> beSensitiveDataItemList) {
        return true;
    }

    /**
     * 校验业务逻辑。
     *
     * @param hasFuzzy                是否为打码输出(打码输出=true;明文输出=false)
     * @param sensitiveDataModule     解密业务模块
     * @param beSensitiveDataItemList 待解密项集合
     * @return 校验成功或失败(不建议直接抛出异常 , 以免影响其他数据解密)
     */
    protected boolean validateBusinessLogic(boolean hasFuzzy, SensitiveDataModuleEnumV2 sensitiveDataModule, List<BeSensitiveDataItem> beSensitiveDataItemList) {
        return true;
    }

    //endregion
}
View Code
复制代码

 

Plugins某子类代码 

复制代码
package com.differ.jackyun.jackyunassservice.service.sensitivedataprocessv2.plugins;

import com.differ.jackyun.jackyunassbase.infrastructure.datacore.BaseContextInfo;
import com.differ.jackyun.jackyunassbase.infrastructure.enums.ErrorCodes;
import com.differ.jackyun.jackyunassbase.infrastructure.exception.AppException;
import com.differ.jackyun.jackyunassbase.infrastructure.utils.CoreUtils;
import com.differ.jackyun.jackyunassbase.infrastructure.utils.ExtUtils;
import com.differ.jackyun.jackyunassservice.dao.jackyunmultidb.common.DaoCommonDBSwitchMapper;
import com.differ.jackyun.jackyunassservice.service.sensitivedataprocessv2.*;
import com.differ.jackyun.jackyunassservice.service.sensitivedataprocessv2.core.DecryptionDataInfo;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 电商平台敏感数据处理方案(明文脱敏)。
 * 从数据库获取明文返回或打码返回
 *
 * @Author hgw
 * @Date 2021-11-01
 */
@Component
@Lazy(true)
public class CleartextSensitiveDataProcess extends BaseSensitiveDataProcessV2 {
    //region 变量

    /**
     * 通用查询数据仓储切库服务
     */
    @Autowired
    private DaoCommonDBSwitchMapper daoCommonDBSwitchMapper;

    //endregion

    //region 重写基类方法

    /**
     * 数据解密
     *
     * @param contextInfo             会员名称
     * @param hasFuzzy                是否为打码输出(打码输出=true;明文输出=false)
     * @param sensitiveDataModule     解密业务模块
     * @param beSensitiveDataItemList 待解密项集合
     */
    @Override
    protected void decryptProfile(BaseContextInfo contextInfo, boolean hasFuzzy, SensitiveDataModuleEnumV2 sensitiveDataModule, List<BeSensitiveDataItem> beSensitiveDataItemList) {
        /**
         * 本模式适用:
         * 1. 明文脱敏
         * 2. 平台密文数据为带掩码格式(淘系平台),打码解密直接从数据库取出数据掐头去尾即可而无需请求平台。
         * ----------------
         * 业务说明:
         * 1. 明文脱敏,直接从数据库中获取明文数据。
         * 2. 如果需要打码,则打码输出,否则输出明文。
         */

        //如果待解密集合为空则直接返回。
        if (CollectionUtils.isEmpty(beSensitiveDataItemList)) {
            return;
        }

        //获取指定模块的所有数据列配置。
        List<SensitiveDataColumnConfigEnumV2> columnConfigList = SensitiveDataColumnConfigEnumV2.getColumnConfig(sensitiveDataModule);
        if (columnConfigList.size() == 0) {
            throw new AppException(ErrorCodes.LOGICERROR, "明文脱敏解密模块“" + sensitiveDataModule.name() + "”下没有任何配置列");
        }

        //对待解密项集合进行分页,防止SQL过大发生异常。
        List<List<BeSensitiveDataItem>> pagingList = CoreUtils.lstPaging(beSensitiveDataItemList, 20);

        //分页数据解密详情方法。
        for (List<BeSensitiveDataItem> list : pagingList) {
            decryptFromDb(contextInfo, hasFuzzy, list, sensitiveDataModule);
        }
    }

    //endregion

    //region 其他方法

    /**
     * 数据解密(从数据库获取)。
     *
     * @param contextInfo             上下文环境信息
     * @param hasFuzzy                是否为打码输出(打码输出=true;明文输出=false)
     * @param beSensitiveDataItemList 待解密项集合
     * @param sensitiveDataModule     解密业务模块
     */
    private void decryptFromDb(BaseContextInfo contextInfo, boolean hasFuzzy, List<BeSensitiveDataItem> beSensitiveDataItemList, SensitiveDataModuleEnumV2 sensitiveDataModule) {
        /**
         * 业务说明:
         * 1. 拼接SQL语句并执行
         * 2. 循环填充结果
         *     1) 过滤掉无效项:数据库中无数据、解密数据为空、非(明文或打码输出且平台密文数据为带掩码格式)
         *     2) 如果需要打码输出,则进行打码。
         *         .明文直接打码
         *         .平台密文数据为带掩码格式(淘系平台),则只需掐头去尾。
         *     3) 所有数据加入字典集
         *     4) 通用字段一一赋值。
         */

        //region 拼接SQL语句并执行

        //拼接业务主键
        String businessKeys = beSensitiveDataItemList.stream().map(g -> g.getBusinessKey()).collect(Collectors.joining(","));
        //获取各个模块的敏感数据。
        List<DecryptionDataInfo> resultList = SensitiveDataProcessUtilsV2.getDecryptionData(contextInfo, this.daoCommonDBSwitchMapper, sensitiveDataModule, businessKeys);

        //endregion

        //region 循环填充结果

        for (BeSensitiveDataItem beSensitiveDataItem : beSensitiveDataItemList) {
            //根据业务主键获取数据查询结果集,如果没有任何数据则略过。
            List<DecryptionDataInfo> resultItemList = resultList.stream().filter(g -> beSensitiveDataItem.getBusinessKey().equalsIgnoreCase(g.getBusinessKey().toString())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(resultItemList)) {
                SensitiveDataProcessUtilsV2.appendDecryptionFailuresMessage(beSensitiveDataItem, "数据库无数据");
                continue;
            }

            //判断是否为打码输出 且 平台密文数据为带掩码格式(淘系平台)
            boolean isMaskData = hasFuzzy && SensitiveDataPlatFeatures.isMaskData(beSensitiveDataItem.getPolyAPIPlat());

            //循环所有解密项。
            resultItemList.forEach(resultItem -> {
                //如果获取到的解密值为空则略过。
                if (ExtUtils.isNullOrEmpty(resultItem.getSensitiveValue())) {
                    return;
                }

                //判断当前数据是否为明文。
                boolean isClearText = SensitiveDataProcessUtilsV2.isClearText(resultItem.getSensitiveValue());

                /**
                 * 业务说明:
                 * 以下情况会略过,原因:
                 *     1) 当从数据库中查询出来的数据为明文时,会覆盖其他解密模式的解密值(以明文为准)。
                 *        当解密项既有明文又有密文时,会同时调用两种解密模式,先其他解密模式,后明文解密模式,从数据库获取到明文覆盖之前的解密值。
                 *     2) 打码输出 且 平台密文数据为带掩码格式(淘系平台),此类只需从数据库查出数据掐头去尾即可。
                 */
                if (!(isClearText || isMaskData)) {
                    return;
                }

                //获取列配置枚举
                SensitiveDataColumnConfigEnumV2 columnConfig = SensitiveDataColumnConfigEnumV2.create(resultItem.getDataType());

                //如果是打码输出,则根据模式进行对应的处理。
                if (hasFuzzy) {
                    String usedMaskText = ClearTextUseMaskUtils.smartUseMaskForJust(columnConfig.getFieldType(), resultItem.getSensitiveValue());
                    resultItem.setSensitiveValue(usedMaskText);
                }

                //加入Map集
                beSensitiveDataItem.getDecryptedResult().getDecryptedDataMap().put(columnConfig, resultItem.getSensitiveValue());

                //通用字段一一赋值
                if (null != columnConfig.getFieldType()) {
                    SensitiveDataProcessUtilsV2.fillSensitiveDataItem(beSensitiveDataItem, columnConfig.getFieldType(), resultItem.getSensitiveValue());
                }
            });
        }

        //endregion
    }

    //endregion
}
View Code
复制代码

 

工厂代码

复制代码
package com.differ.jackyun.jackyunassservice.service.sensitivedataprocessv2;

import com.differ.jackyun.jackyunassbase.infrastructure.enums.ErrorCodes;
import com.differ.jackyun.jackyunassbase.infrastructure.exception.AppException;
import com.differ.jackyun.jackyunassbase.infrastructure.utils.SpringResolveManager;
import com.differ.jackyun.jackyunassservice.service.sensitivedataprocessv2.plugins.*;

/**
 * 敏感数据处理类工厂
 *
 * @Author hgw
 * @Date 2021-11-01
 * 有以下解密模式:
 * -----------------------------
 * 淘系(oaid):http://192.168.88.47/web/#/5?page_id=14225
 * 非淘系(非oaid、拼多多打码解密):http://192.168.88.47/web/#/5?page_id=14251
 * 京东代理:http://showdoc.happylife.ren/web/#/5?page_id=10825
 * 拼多多代理(仅明文解密):http://showdoc.happylife.ren/web/#/5?page_id=10825
 * 明文解密(明文解密、淘系部分平台打码输出走明文模式):直接从数据库获取明文(或打码)输出;淘系部分平打过码输出只需从数据库获取数据后掐头去尾
 */
public class SensitiveDataProcessFactoryV2 {
    /**
     * 根据条件创建ISensitiveDataProcess对象。
     *
     * @param sensitiveDataMode 解密模式
     * @return ISensitiveDataProcess对象
     */
    public static ISensitiveDataProcessV2 create(SensitiveDataModeEnum sensitiveDataMode) {
        switch (sensitiveDataMode) {
            case OAID:
                return SpringResolveManager.resolve(OaIdSensitiveDataProcess.class);
            case CIPHERTEXT:
                return SpringResolveManager.resolve(CiphertextSensitiveDataProcess.class);
            case CLEARTEXT:
                return SpringResolveManager.resolve(CleartextSensitiveDataProcess.class);
            case JD_PROXY:
                return SpringResolveManager.resolve(JdProxySensitiveDataProcess.class);
            case PDD_PROXY:
                return SpringResolveManager.resolve(PddProxySensitiveDataProcess.class);
            case ORIGINALCIPHERTEXT:
                return SpringResolveManager.resolve(OriginalTextProxySensitiveDataProcess.class);
            default:
                throw new AppException(ErrorCodes.LOGICERROR, "未实现解密模式为“" + sensitiveDataMode.name() + "”处理方案");
        }
    }
}
View Code
复制代码

 

辅助类部分代码

复制代码
    //region 数据脱敏解密

    /**
     * 数据脱敏解密。
     *
     * @param contextInfo 上下文环境信息
     * @param queryOption 业务数据(敏感数据脱敏)
     * @return 输出业务数据(敏感数据脱敏)
     */
    public static DecryptingDataQueryResult decrypt(BaseContextInfo contextInfo, DecryptingDataQueryOption queryOption) {
        //region 构建相关对象

        //创建返回结果对象。
        DecryptingDataQueryResult queryResult = new DecryptingDataQueryResult();
        List<DecryptingDataQueryResult.Item> queryResultItemList = new ArrayList<>();
        queryResult.setItems(queryResultItemList);
        queryResult.setContextId(contextInfo.getContextID());

        //根据请求参数集构建所有待解密项集合
        List<BeSensitiveDataItem> allBeSensitiveDataItemList = new ArrayList<>(queryOption.getItems().size());
        queryOption.getItems().forEach(g -> {
            //构建对象加入集合并映射。
            BeSensitiveDataItem beSensitiveDataItem = new BeSensitiveDataItem();
            MapperUtils.map(g, beSensitiveDataItem);
            beSensitiveDataItem.setField(queryOption.getField());
            allBeSensitiveDataItemList.add(beSensitiveDataItem);

            //初始化解密结果对象
            DecryptingDataResult decryptedResult = new DecryptingDataResult();
            beSensitiveDataItem.setDecryptedResult(decryptedResult);
            Map<SensitiveDataColumnConfigEnumV2, String> decryptedDataMap = new HashMap<>(CollectionsUtil.getHashCapacity(20));
            decryptedResult.setDecryptedDataMap(decryptedDataMap);
        });

        //表示已处理的业务主键集。
        List<String> processedBusinessKeyList = new ArrayList<>();

        //是否为打码解密。
        boolean hasFuzzy = Boolean.TRUE.equals(queryOption.getbHasFuzzy());

        //endregion

        if (SensitiveDataSceneEnum.ORIGINALTEXT.equals(queryOption.getScene())) {
            //region 获取原始密文解密

            /**
             * 直接从api数据库里查询原始密文数据
             */
            decryptProfile(contextInfo, queryOption, processedBusinessKeyList, allBeSensitiveDataItemList, SensitiveDataModeEnum.ORIGINALCIPHERTEXT,
                    (g) -> {
                        return true;
                    }
            );

            //endregion
        }

        //region 京东代理解密

        /**
         * 过滤条件:
         * 1. 除排已处理项
         * 2. 京东平台解密
         */
        decryptProfile(contextInfo, queryOption, processedBusinessKeyList, allBeSensitiveDataItemList, SensitiveDataModeEnum.JD_PROXY,
                (g) -> {
                    return !processedBusinessKeyList.contains(g.getBusinessKey())
                            && PolyAPIPlatEnum.isJd(g.getPolyAPIPlat());
                }
        );

        //endregion

        //region 拼多多代理解密

        /**
         * 过滤条件:
         * 1. 除排已处理项
         * 2. 拼多多明文解密
         * 注:拼多多打码解密走密文模式数据脱敏
         */
        decryptProfile(contextInfo, queryOption, processedBusinessKeyList, allBeSensitiveDataItemList, SensitiveDataModeEnum.PDD_PROXY,
                (g) -> {
                    return !processedBusinessKeyList.contains(g.getBusinessKey())
                            && PolyAPIPlatEnum.isPdd(g.getPolyAPIPlat())
                            && !hasFuzzy;
                }
        );

        //endregion

        //region oaid模式数据脱敏

        /**
         * 过滤条件:
         * 1. 除排已处理项
         * 2. 有密文数据
         * 3. 且 通过oaid解密。
         * 4. 且 非(打码输出 且 平台密文数据为带掩码格式(淘系平台))。
         * 注:打码输出 且 平台密文数据为带掩码格式(淘系平台),走明文数据脱敏。
         */

        decryptProfile(contextInfo, queryOption, processedBusinessKeyList, allBeSensitiveDataItemList, SensitiveDataModeEnum.OAID,
                (g) -> {
                    return !processedBusinessKeyList.contains(g.getBusinessKey())
                            && Boolean.TRUE.equals(g.getHasCipherText())
                            && SensitiveDataPlatFeatures.needOaid(g.getPolyAPIPlat())
                            && !(hasFuzzy && SensitiveDataPlatFeatures.isMaskData(g.getPolyAPIPlat()));
                }
        );

        //endregion

        //region 密文模式数据脱敏

        /**
         * 过滤条件:
         * 1. 除排已处理项
         * 2. 有密文数据
         * 3. 且 不通过oaid解密。
         */

        decryptProfile(contextInfo, queryOption, processedBusinessKeyList, allBeSensitiveDataItemList, SensitiveDataModeEnum.CIPHERTEXT,
                (g) -> {
                    return !processedBusinessKeyList.contains(g.getBusinessKey())
                            && Boolean.TRUE.equals(g.getHasCipherText())
                            && !SensitiveDataPlatFeatures.needOaid(g.getPolyAPIPlat());
                }
        );

        //endregion

        //region 明文模式数据脱敏

        /**
         * 过滤条件:
         * 1. 非销售单解密(销售单数据在OMS,不存在售后明文解密)
         * 2. 且 (有明文数据 或 打码输出且平台密文数据为带掩码格式(淘系平台),打码解密直接从数据库取出数据掐头去尾即可)
         *
         * 特别说明:
         * 1. 明文解密模式不除排已处理项
         * 2. 明文模式数据脱敏要放到最后,因为数据里有可能既有明文又有密文。
         * 3. 明文解密用数据库中的明文替换相应的结果集字段,以数据库中的明文为准。
         * 4. 对于售后单中的敏感信息,最初从网店订单中引用(为密文),但是后期客户可能会修改这些敏感数据(为明文),故一个售后单中的敏感信息既有密文、也有明文。
         */

        decryptProfile(contextInfo, queryOption, processedBusinessKeyList, allBeSensitiveDataItemList, SensitiveDataModeEnum.CLEARTEXT,
                (g) -> {
                    return !queryOption.getModule().equals(SensitiveDataModuleEnumV2.TRADE)
                            && (Boolean.TRUE.equals(g.getHasClearText()) || (hasFuzzy && SensitiveDataPlatFeatures.isMaskData(g.getPolyAPIPlat())));
                }
        );

        //endregion

        //region 填充返回结果

        allBeSensitiveDataItemList.forEach(g -> {
            DecryptingDataQueryResult.Item queryResultItem = new DecryptingDataQueryResult.Item();
            queryResultItemList.add(queryResultItem);
            MapperUtils.map(g, queryResultItem);
        });

        //endregion

        return queryResult;
    }

    //endregion
View Code
复制代码

 

posted @   有容乃大  阅读(339)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示