【后端】处理手机号脱敏

本文介绍了一款针对Java应用的敏感数据脱敏工具的实现方法。该工具能够对多种类型的敏感信息进行自动脱敏处理,包括中文姓名、身份证号、电话号码等,确保在展示或传输过程中保护个人隐私。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

  1.  mobilenumber = mobilenumber.substring(0, 3) + "***"

                           + mobilenumber.substring(length - 4, length);

  2. @Desensitization(desensitization=DesensitizationEnum.MOBILE_PHONE)

    private String mobilenumber;

  3. ResponseVO<List<CustInfos>> responseVO = custInfoService.selectCustInfoList(formMap);

            LOGGER.info("条件查询客户列表查询结果:" + responseVO.getResult());

            List<CustInfos> custInfolist = responseVO.getData();

            custInfolist = DesensitizationUtils.desensitizationList(custInfolist);

 

 

/**

 * 脱敏工具

 */

public class DesensitizationUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(DesensitizationUtils.class);

    /**

     * 脱敏

     * @param objList

     * @return

     */

    public static <T> List<T> desensitizationList(List<T> objList) {

        List<T> dobjList = new ArrayList<T>();

        for (T obj : objList) {

            dobjList.add(desensitization(obj));

        }

        return dobjList;

    }

    /**

     * 脱敏

     * @param obj

     * @return

     */

    public static <T> T desensitization(T obj) {

        try {

            Class<? extends Object> clazz = obj.getClass();

            //获取所有自己声明的属性 

            Field[] fields = clazz.getDeclaredFields();

            //遍历属性 

            for (Field field : fields) {

                //通过注解中的值来获取属性名(注解中的值应该与属性名相等) 

                Desensitization columnField = field.getAnnotation(Desensitization.class);

                //如果是没有注解的属性忽略掉

                if (null == columnField) {

                    continue;

                }

                String type = field.getGenericType().toString(); //获取属性的类型 

                PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);

                Method rM = pd.getReadMethod();//获得读方法   

                Object oldValue = (Object) rM.invoke(obj);

                Object newValue = oldValue;

                if (null != oldValue) {

                    Method wM = pd.getWriteMethod();//获得写方法   

                    DesensitizationEnum desensitizationValue = columnField.desensitization();

                    String doMethodName = "do"

                                          + desensitizationValue.toString().replace("_", "")

                                              .substring(0, 1).toUpperCase()

                                          + desensitizationValue.toString().replace("_", "")

                                              .toLowerCase().substring(1);

                    Method getMethod = DesensitizationUtils.class.getDeclaredMethod(doMethodName,

                        String.class, Object.class);

                    newValue = getMethod.invoke(DesensitizationUtils.class, type, oldValue);

                    wM.invoke(obj, newValue);

                }

            }

        } catch (Exception e) {

            LOGGER.error("脱敏处理失败{}", e);

        }

        return obj;

    }

    /**

     * [中文姓名] 只显示第一个汉字,其他隐藏为星号<例子:李**>

     */

    public static Object doChinesename(String type, Object oldValue) {

        //判断字符串,多个中满足任何一个用IN,并使用'' 

        if (!type.equals("class java.lang.String")) {

            LOGGER.info("不支持的数据类型{}", type);

            throw new RuntimeException("不支持的数据类型");

        }

        //字符串表示法 

        String fullName = oldValue.toString();

        String name = StringUtils.left(fullName, 1);

        return StringUtils.rightPad(name, fullName.length(), "*");

    }

    /**

     * [身份证号] 显示最后四位,其他隐藏。共计18位或者15位。<例子:*************5762>

     * @return

     */

    public static Object doIdcard(String type, Object oldValue) {

        //判断字符串,多个中满足任何一个用IN,并使用'' 

        if (!type.equals("class java.lang.String")) {

            LOGGER.info("不支持的数据类型{}", type);

            throw new RuntimeException("不支持的数据类型");

        }

        //字符串表示法 

        String id = oldValue.toString();

        int length = id.length();

        if (length <= 4) {

            return id;

        }

        String num = StringUtils.right(id, 4);

        return StringUtils.leftPad(num, id.length(), "*");

    }

    /**

     * [固定电话] 后四位,其他隐藏<例子:****1234>

     */

    public static Object doFixedphone(String type, Object oldValue) {

        //判断字符串,多个中满足任何一个用IN,并使用'' 

        if (!type.equals("class java.lang.String")) {

            LOGGER.info("不支持的数据类型{}", type);

            throw new RuntimeException("不支持的数据类型");

        }

        //字符串表示法 

        String num = oldValue.toString();

        int length = num.length();

        if (length <= 4) {

            return num;

        }

        return StringUtils.leftPad(StringUtils.right(num, 4), num.length(), "*");

    }

    /**

     * [手机号码] 前三位,后四位,其他隐藏<例子:138******1234>

     * 

     * @return

     */

    public static Object doMobilephone(String type, Object oldValue) {

        //判断字符串,多个中满足任何一个用IN,并使用'' 

        if (!type.equals("class java.lang.String")) {

            LOGGER.info("不支持的数据类型{}", type);

            throw new RuntimeException("不支持的数据类型");

        }

        //字符串表示法 

        String mobilnumber = oldValue.toString();

        int length = mobilnumber.length();

        if (length <= 7) {

            return mobilnumber;

        }

        return StringUtils.left(mobilnumber, 3).concat(

            StringUtils.removeStart(

                StringUtils.leftPad(StringUtils.right(mobilnumber, 4), mobilnumber.length(), "*"),

                "***"));

    }

    /**

     * [地址] 只显示到地区,不显示详细地址;我们要对个人信息增强保护<例子:北京市海淀区****>

     */

    public static Object doAddress(String type, Object oldValue) {

        //判断字符串,多个中满足任何一个用IN,并使用'' 

        if (!type.equals("class java.lang.String")) {

            LOGGER.info("不支持的数据类型{}", type);

            throw new RuntimeException("不支持的数据类型");

        }

        //字符串表示法 

        String address = oldValue.toString();

        int length = address.length();

        if (length <= 2) {

            return address;

        }

        return StringUtils.rightPad(StringUtils.left(address, length / 2), length, "*");

    }

    /**

     * [电子邮箱] 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示<例子:g**@163.com> 

     */

    public static Object doEmail(String type, Object oldValue) {

        //判断字符串,多个中满足任何一个用IN,并使用'' 

        if (!type.equals("class java.lang.String")) {

            LOGGER.info("不支持的数据类型{}", type);

            throw new RuntimeException("不支持的数据类型");

        }

        //字符串表示法 

        String email = oldValue.toString();

        int index = StringUtils.indexOf(email, "@");

        if (index <= 1) {

            return email;

        }

        return StringUtils.rightPad(StringUtils.left(email, 1), index, "*").concat(

            StringUtils.mid(email, index, email.length()));

    }

    /**

     * [银行卡号] 前六位,后四位,其他用星号隐藏每位1个星号<例子:6222600**********1234>

     */

    public static Object doBankcard(String type, Object oldValue) {

        //判断字符串,多个中满足任何一个用IN,并使用'' 

        if (!type.equals("class java.lang.String")) {

            LOGGER.info("不支持的数据类型{}", type);

            throw new RuntimeException("不支持的数据类型");

        }

        //字符串表示法 

        String cardNum = oldValue.toString();

        int length = cardNum.length();

        if (length <= 10) {

            return cardNum;

        }

        return StringUtils.left(cardNum, 6).concat(

            StringUtils.removeStart(

                StringUtils.leftPad(StringUtils.right(cardNum, 4), length, "*"), "******"));

    }

}

<think>首先,用户的问题是:“我想使用JavaScript对手机号码进行脱敏处理请问JavaScript手机号脱敏方法”。根据系统指令,我需要生成相关问题,并使用中文回答。用户提供的引用包括几个JavaScript脱敏方法的例子:-引用[1]:使用substring方法,取出前三位和后四位,中间用*替换。-引用[2]:使用正则表达式替换。-引用[3]:使用循环遍历字符串,保留前三位和后四位。 -引用[4]:使用substring和substr方法。 我的回答需要结构清晰,帮助用户逐步解决问题。我应该基于这些引用提供可靠的脱敏方法。关键点:-手机号码通常11位,但代码应处理不同长度的情况。 -常见策略是保留前三位和后四位,中间部分用*替换。-提供代码示例,并解释其工作原理。 回答结构:1.**介绍脱敏概念**:简要解释什么是手机号脱敏及其重要性。2.**提供方法**:给出几种常见的JavaScript实现方法,包括代码示例。3. **解释和优化**:解释每种方法,讨论其优缺点。 4. **生成相关问题**:在末尾添加相关问题,符合系统指令。 使用LaTeX格式:-行内数学表达式用$...$,但在这个上下文中可能不需要数学表达式,除非涉及计算。-独立公式用$$...$$,但这里没有复杂公式。-确保LaTeX语法正确。添加引用标识: -在引用的段落末尾自然地添加[^1],[^2]等。由于用户提供了引用,我应该引用它们。最终回答:-以中文撰写。 -清晰、可靠。 相关问题: -根据系统指令,生成相关问题,放在“§§相关问题§§”部分。 -问题应基于主题,比如性能、优化、应用场景。相关问题想法: 1.如何优化手机号脱敏的性能? 2.脱敏方法如何处理不同国家的手机号码格式?3.除了手机号码,还有哪些常见的信息需要脱敏?4.脱敏在数据安全中的应用场景?现在,构建回答:###回答主体1. **介绍**:手机号脱敏是为了保护用户隐私,通过隐藏部分数字。常见方法是保留前三位和后四位,中间用星号替换。 2. **方法1:使用substring方法**-代码示例:基于引用[1]和[4]。-解释:获取字符串的前三位和后四位,中间用*填充。3. **方法2:使用正则表达式**-代码示例:基于引用[2]。-解释:使用正则匹配和替换。4.**方法3:使用循环**-代码示例:基于引用[3]。-解释:遍历每个字符,保留特定位置的字符。5.**比较和推荐**:讨论哪种方法更高效或易读。推荐使用substring或正则表达式,因为它们更简洁。6.**完整代码示例**:提供一个通用的函数。###代码格式-使用代码块,如示例中所示。###添加引用-在描述方法时,引用相应的来源。###相关问题-在末尾添加3-4个相关问题。</think>### JavaScript 手机号脱敏方法 手机号脱敏是保护用户隐私的重要手段,通过隐藏部分敏感数字(如中间四位),确保数据在显示或传输时不被滥用。以下是几种可靠且高效的 JavaScript 实现方法,基于常见实践和最佳参考方案。所有方法均假设手机号为 11 位标准格式(如 "13812345678"),但包含长度校验以增强鲁棒性。 #### 方法 1:使用 `substring` 和字符串拼接(推荐) 这是最简洁高效的方式,直接截取前三位和后四位,中间用 `*` 填充。适用于大多数场景。 ```javascript function desensitizePhone(phone) { if (typeof phone !== 'string' || phone.length < 7) { return phone; // 长度不足时直接返回原值 } const firstThree = phone.substring(0, 3); // 获取前三位 const lastFour = phone.substring(phone.length - 4); // 获取后四位 return `${firstThree}${'*'.repeat(phone.length - 7)}${lastFour}`; // 中间部分脱敏 } // 测试 console.log(desensitizePhone("13812345678")); // 输出: "138****5678" console.log(desensitizePhone("12345")); // 输出: "12345"(长度不足) ``` - **优点**:代码简洁,性能高(时间复杂度 $O(1)$)。 - **缺点**:对非标准长度手机号处理较简单,需额外校验[^1][^4]。 #### 方法 2:使用正则表达式替换 通过正则匹配实现灵活脱敏,适合需要动态调整脱敏规则的情况(如不同国家的号码格式)。 ```javascript function desensitizePhoneRegex(phone) { if (!phone) return ''; return phone.replace(/^(\d{3})(\d+)(\d{4})$/, (_, prefix, middle, suffix) => { return `${prefix}${'*'.repeat(middle.length)}${suffix}`; // 中间部分替换为* }); } // 测试 console.log(desensitizePhoneRegex("13987654321")); // 输出: "139****4321" ``` - **优点**:灵活性强,可扩展其他脱敏规则(如身份证号)。 - **缺点**:正则表达式可能略慢于直接字符串操作(时间复杂度 $O(n)$),需注意异常输入[^2]。 #### 方法 3:使用循环遍历字符 手动遍历字符串,保留前三位和后四位,中间替换为指定字符。适合教学或自定义脱敏逻辑。 ```javascript function desensitizePhoneLoop(phone, maskChar = '*') { if (phone.length < 11) return phone; let result = ''; for (let i = 0; i < phone.length; i++) { result += (i < 3 || i >= phone.length - 4) ? phone[i] : maskChar; // 保留首尾,替换中间 } return result; } // 测试 console.log(desensitizePhoneLoop("13700001111")); // 输出: "137****1111" ``` - **优点**:逻辑清晰,易于自定义脱敏位置。 - **缺点**:性能较低(时间复杂度 $O(n)$),不推荐大数据量场景[^3]。 ### 最佳实践建议 1. **输入校验**:始终检查输入是否为字符串,并处理长度异常(如小于 7 位)。 2. **脱敏字符**:默认使用 `*`,但可通过参数自定义(如 `desensitizePhone(phone, '#')`)。 3. **扩展性**:结合方法 2 的正则,可统一处理其他敏感信息(如身份证、邮箱)[^2][^3]。 4. **安全性**:脱敏仅用于前端展示,敏感数据存储仍需后端加密。 ### 性能比较 | 方法 | 时间复杂度 | 适用场景 | |------------|------------|-------------------| | substring | $O(1)$ | 高性能需求 | | 正则表达式 | $O(n)$ | 灵活规则匹配 | | 循环遍历 | $O(n)$ | 教学或自定义逻辑 | > 引用说明:以上方法综合了常见实现方案,确保代码可靠性和易用性[^1][^2][^3][^4]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值