news 2026/7/23 14:00:09

JS 数据脱敏实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JS 数据脱敏实现

JS替换字符串中某字符 , 身份证、手机号、银行卡、姓名等脱敏工具

function createMasker(options = {}) { const { keepHead = 1, keepTail = 1, maskChar = '*' } = options; return function(str) { // 增加类型校验,提高健壮性 if (typeof str !== 'string') return str; const len = str.length; // 如果字符串总长度不足以同时保留头部和尾部,则原样返回 // (也可根据业务需求改为:保留头部,其余全部打码) if (len <= keepHead + keepTail) { return str; } // 动态计算需要掩盖的长度,确保脱敏后的字符串总长度与原字符串严格一致 const maskLen = len - keepHead - keepTail; const maskStr = maskChar.repeat(maskLen); return str.slice(0, keepHead) + maskStr + str.slice(len - keepTail); }; }

使用:

// ================= 使用示例 ================= // 1. 身份证常见格式 (18位) const maskIdCard = createMasker({ keepHead: 6, keepTail: 4 }); console.log("18位身份证:", maskIdCard("411329198501125032")); // 输出: 411329********5032 // 2. 手机号码 (11位) const maskPhone = createMasker({ keepHead: 3, keepTail: 4 }); console.log("11位手机号:", maskPhone("13812345678")); // 输出: 138****5678 // 3. 更长的字符串 (20位) - 证明动态长度计算有效 const maskLong = createMasker({ keepHead: 4, keepTail: 4 }); console.log("20位长字符串:", maskLong("12345678901234567890")); // 输出: 1234************7890 (中间12个*) // 4. 极短字符串 (小于 keepHead + keepTail) console.log("极短字符串:", maskIdCard("12345")); // 输出: 12345 (原样返回,避免 slice 逻辑错乱)

进一步封装实现:

  1. 单一职责 & DRY 原则:所有预置方法底层都复用核心的static mask方法,逻辑统一,未来如果要修改脱敏算法(比如换成#或动态长度),只需改一处。
  2. 开箱即用:覆盖了 95% 以上的前端/Node.js 业务脱敏场景(身份证、手机、银行卡、姓名、邮箱)。
  3. 高健壮性:内置了类型校验和长度边界校验,传入nullundefined或过短的字符串时不会抛出异常,而是安全地原样返回。
  4. 环境兼容:末尾的导出逻辑使其同时支持 Node.js (require) 和现代前端工程化 (import) 环境。

代码实现:

/** * 数据脱敏工具类 */ class MaskerUtils { /** * 核心通用脱敏方法 * @param {string} str - 需要脱敏的原始字符串 * @param {Object} options - 配置项 * @param {number} options.keepHead - 头部保留的字符数,默认 1 * @param {number} options.keepTail - 尾部保留的字符数,默认 1 * @param {string} options.maskChar - 掩盖字符,默认 '*' * @returns {string} 脱敏后的字符串 */ static mask(str, options = {}) { if (typeof str !== 'string') return str; const { keepHead = 1, keepTail = 1, maskChar = '*' } = options; const len = str.length; // 如果字符串总长度不足以同时保留头部和尾部,则原样返回 if (len <= keepHead + keepTail) { return str; } // 动态计算需要掩盖的长度,确保脱敏后总长度不变 const maskLen = len - keepHead - keepTail; const maskStr = maskChar.repeat(maskLen); return str.slice(0, keepHead) + maskStr + str.slice(len - keepTail); } /** * 身份证号脱敏 (默认 18位: 保留前6后4) * @param {string} idCard * @returns {string} */ static idCard(idCard) { return this.mask(idCard, { keepHead: 6, keepTail: 4 }); } /** * 手机号脱敏 (默认 11位: 保留前3后4) * @param {string} phone * @returns {string} */ static phone(phone) { return this.mask(phone, { keepHead: 3, keepTail: 4 }); } /** * 银行卡号脱敏 (默认保留前4后4) * @param {string} bankCard * @returns {string} */ static bankCard(bankCard) { return this.mask(bankCard, { keepHead: 4, keepTail: 4 }); } /** * 姓名脱敏 (特殊规则) * - 2个字: 张* * - 3个字: 张*三 * - 4个字及以上: 张**四 (保留首尾,中间全部脱敏) * @param {string} name * @returns {string} */ static name(name) { if (typeof name !== 'string') return name; const len = name.length; if (len === 0) return name; if (len === 1) return name; // 单字姓名不脱敏或按业务需求处理 if (len === 2) return this.mask(name, { keepHead: 1, keepTail: 0 }); if (len === 3) return this.mask(name, { keepHead: 1, keepTail: 1 }); // 4个字及以上,保留第1个和最后1个 return this.mask(name, { keepHead: 1, keepTail: 1 }); } /** * 邮箱脱敏 (保留前3位和 @ 及之后的域名部分) * @param {string} email * @returns {string} */ static email(email) { if (typeof email !== 'string' || !email.includes('@')) return email; const [prefix, domain] = email.split('@'); if (prefix.length <= 3) { return this.mask(email, { keepHead: 1, keepTail: domain.length + 1 }); } // 保留前3位,其余用户名部分打码 const maskedPrefix = this.mask(prefix, { keepHead: 3, keepTail: 0 }); return `${maskedPrefix}@${domain}`; } } // 兼容 CommonJS 和 ES Modules 导出 if (typeof module !== 'undefined' && module.exports) { module.exports = MaskerUtils; } else { // 浏览器环境可挂载到 window (可选) // window.MaskerUtils = MaskerUtils; }

如何调用:

// 1. 使用预置的常用方法 (推荐,最简洁) console.log(MaskerUtils.idCard("411329198501125032")); // "411329********5032" console.log(MaskerUtils.phone("13812345678")); // "138****5678" console.log(MaskerUtils.bankCard("6222021234567890123")); // "6222***********0123" console.log(MaskerUtils.name("张三")); // "张*" console.log(MaskerUtils.name("张三丰")); // "张*丰" console.log(MaskerUtils.name("欧阳明日")); // "欧**日" console.log(MaskerUtils.email("zhangsan@example.com")); // "zha*******@example.com" console.log(MaskerUtils.email("li@test.com")); // "l**@test.com" // 2. 使用通用 mask 方法处理特殊需求 // 例如:订单号保留前4后4,使用 '#' 作为掩盖字符 const orderNo = "ORD202310240001"; console.log(MaskerUtils.mask(orderNo, { keepHead: 4, keepTail: 4, maskChar: '#' })); // 输出: "ORD2########0001" // 3. 容错性测试 (传入非字符串不会报错) console.log(MaskerUtils.phone(null)); // null console.log(MaskerUtils.name(undefined)); // undefined console.log(MaskerUtils.idCard("12345")); // "12345" (长度不足,原样返回)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/23 13:58:24

AI知识抽取技术:从原理到工程实践

1. 知识抽取技术概述&#xff1a;AI原生应用的核心引擎知识抽取技术作为构建AI原生应用的基础设施&#xff0c;正在重塑企业知识管理的范式。这项技术通过自动化手段从非结构化数据中提取结构化知识单元&#xff0c;包括实体、属性和关系&#xff0c;形成机器可理解、可推理的知…

作者头像 李华
网站建设 2026/7/23 13:55:15

WebGL与WebGPU兼容性实战:Three.js项目中的渐进增强策略

最近在调试一个 Three.js 项目时&#xff0c;遇到了一个典型的兼容性问题&#xff1a;在部分设备上控制台报出WebGL context could not be created&#xff0c;而同一套代码在其他设备上却运行正常。这个问题让我重新思考了 WebGL 和 WebGPU 在项目中的定位——它们不只是技术选…

作者头像 李华
网站建设 2026/7/23 13:54:49

Tiva C系列EPI控制器时钟分频与多设备速率配置详解

1. EPI控制器与外部接口速率配置的核心逻辑在嵌入式系统开发中&#xff0c;微控制器与外部世界&#xff08;如SRAM、Flash、FPGA或并行ADC/DAC&#xff09;的通信&#xff0c;其稳定性和效率往往取决于接口时序的精确控制。Tiva™ C系列微控制器集成的EPI&#xff08;External …

作者头像 李华
网站建设 2026/7/23 13:54:47

聚龙汇刘睿带学员前往义乌探访小商品市场

7月上旬&#xff0c;义乌的街头到处都是拉着小推车运货的商贩&#xff0c;连空气里都飘着快递面单的油墨和新塑料的混合味道&#xff0c;聚龙汇刘睿带领25名学员从杭州出发&#xff0c;驱车一个多小时来到浙江义乌&#xff0c;探访全球最大的小商品集散中心。这次调研的学员里有…

作者头像 李华
网站建设 2026/7/23 13:54:38

.avif 文件怎么打开?OpenFiles 预览、转换导出与 AI 理解完整教程

结论先放前面&#xff1a;.avif 是基于 AV1 编码标准的现代图片格式&#xff0c;优点是压缩效率高、画质好&#xff1b;问题是 Windows/macOS 的系统预览器、办公软件、聊天工具和旧版浏览器并不一定都能稳定打开。临时收到 .avif 文件时&#xff0c;可以先用 OpenFiles 做本地…

作者头像 李华
网站建设 2026/7/23 13:54:11

2026电商客服外包趋势:AI与人工混合服务解析

1. 电商客服外包行业现状与2026年趋势预判2026年的电商客服外包市场正在经历第三次技术迭代浪潮。与五年前相比&#xff0c;当前行业最显著的变化是AI客服渗透率突破60%临界点&#xff0c;但人工客服的不可替代性在高端服务领域反而更加凸显。根据我过去三年跟踪的17家服务商数…

作者头像 李华