基于JavaScript实现一个动态脱敏指令

 更新时间:2024年12月28日 13:53:48   作者:JYeontu  
数据脱敏是指在不影响数据分析结果的准确性前提下,对原始数据中的敏感字段进行处理,从而降低数据敏感度和减少个人隐私风险的技术措施,下面我们就来看看如何实现一个动态脱敏指令吧

所谓的数据脱敏,是指在不影响数据分析结果的准确性前提下,对原始数据中的敏感字段进行处理,从而降低数据敏感度和减少个人隐私风险的技术措施。在现在这个大数据时代,个人隐私信息在互联网上传播的几率是很大的,因此作为前端工程师,我们很多时候也需要在视图层面对数据进行脱敏展示处理。

效果展示

体验地址

http://jyeontu.xyz/jvuewheel/#/JDesensitizationView

指令实现

脱敏函数

参数处理

  • 接受三个参数 str(待脱敏的字符串)、config(脱敏配置对象)和 fn(可选的自定义处理函数)。首先对 str 进行了 trim 操作并强制转换为字符串类型,确保输入数据的规范性。
  • 若存在自定义函数 fn,则直接调用该函数并返回结果,给予开发者灵活定制脱敏逻辑的空间。
  • 当 str 为空字符串时,直接返回空,简洁处理边界情况。
const desensitization = (str, config, fn) => {
    str = str.trim() + "";
    if (fn) {
        return fn(str);
    }
    if (!str) {
        return "";
    }
    …………
}

配置解析与默认值设定

  • 从 config 中解构出 before(脱敏前保留的字符数)和 after(脱敏后保留的字符数),并提供了默认值 0。同时获取 type(数据类型标识,如 phoneemail 等)和 ch(用于替换敏感字符的符号,默认为 *)。
  • 根据不同的 type,对 before 和 after 进行了智能的默认值调整。例如对于 phone 类型,若字符串长度小于 11,则合理调整 before 为 2,after 为 2,以适配常见的手机号码格式;对于 email 类型,则根据 @ 符号分割字符串来确定 after 的值,精准定位域名部分进行保护。
let { before = 0, after = 0 } = config;
const { type, ch = "*" } = config;
const len = str.length;
switch (type) {
    case "phone":
        before = "3";
        after = "4";
        if (len < 11) {
            before = 2;
            after = 2;
        }
        break;
    case "email":
        before = "1";
        if (str.split("@").length > 1) after = str.split("@")[1].length + 1;
        break;
    case "idCard":
        before = "3";
        after = "4";
        break;
    case "name":
        before = "1";
        after = len > 2 ? 1 : 0;
        break;
}

构造正则进行脱敏

计算出需要显示的真实字符数 show,基于此构建正则表达式 reg。通过 replace 方法,按照正则表达式的匹配规则,用指定的 ch 符号替换中间的敏感字符,最终返回脱敏后的字符串。

const show = Math.max(len - before - after, 0);
const reg = [
    new RegExp(`^(.{${before}}).{${show}}(.{${after}})$`),
    `$1${ch.repeat(show)}$2`,
];
return str.replace(reg[0], reg[1]);

指令执行函数

参数提取与初始值获取

从指令绑定的值 binding.value 中提取出 params,进一步解构得到 config 和 fn。同时获取元素 el 的相关属性值,如 innerHTMLgetAttribute 获取的原始值 originVal,并初始化 inputOriginVal,为后续处理用户输入做准备。

const params = binding.value || {};
const { config, fn } = params;
let inputOriginVal = "";
let originVal = el.getAttribute("desensitization-originVal") || "";

文本节点脱敏处理

当 el.innerHTML 存在时,意味着是对页面展示的文本内容进行脱敏。首先确保 originVal 的获取,若为空则从 el.innerText 中获取并设置为原始值,存储在自定义属性 desensitization-originVal 中,然后调用 desensitization 函数对 originVal 进行脱敏处理,并更新 el.innerHTML

if (el.innerHTML) {
    if (!originVal) {
        el.setAttribute("desensitization-originVal", el.innerText);
        originVal = el.innerText;
    }
    el.innerHTML = desensitization(originVal, config, fn);
    return;
}

输入框交互处理

针对输入框元素,先移除之前可能存在的焦点和失焦事件监听器,避免重复绑定。然后分别为 focus 和 blur 事件添加监听器。在 focus 事件中,将输入框的值恢复为原始输入值 inputOriginVal;在 blur 事件中,获取当前输入值 value,更新 inputOriginVal,并调用 desensitization 函数对 value 进行脱敏处理,最后更新输入框的显示值。

if (fouceListerner) {
    el.removeEventListener("focus", fouceListerner);
}
fouceListerner = el.addEventListener("focus", (event) => {
    event.target.value = inputOriginVal;
});
if (blurListerner) {
    el.removeEventListener("blur", blurListerner);
}
blurListerner = el.addEventListener("blur", (event) => {
    const value = event.target.value;
    inputOriginVal = value;
    const newVal = desensitization(value, config, fn);
    event.target.value = newVal;
});

指令生命周期钩子

bind

当指令首次绑定到元素上时执行。在此处调用 doDesensitization 函数,尝试进行脱敏处理,若出现错误则捕获并打印 bindErr 相关的错误信息,确保指令初始化的稳定性。

bind: function (el, binding) {
    try {
        doDesensitization(el, binding);
    } catch (err) {
        console.error("bindErr", err);
    }
}

update

当指令所在组件的数据更新时触发。首先判断元素 el 的 innerText 是否存在,若存在则调用 doDesensitization 函数进行重新脱敏处理,同样对错误进行捕获并打印 updateErr,保证数据更新后的脱敏效果持续有效。

update: function (el, binding) {
    if (!el.innerText) return;
    try {
        doDesensitization(el, binding);
    } catch (err) {
        console.error("updateErr", err);
    }
}

unbind

当指令从元素上移除时执行。主要任务是移除之前绑定的焦点和失焦事件监听器。

unbind: function (el) {
    if (fouceListerner) {
        el.removeEventListener("focus", fouceListerner);
    }
    if (blurListerner) {
        el.removeEventListener("blur", blurListerner);
    }
}

指令使用

电话号码脱敏

内置有电话的脱敏类型,对于11位数的手机号码,脱敏方式是显示前3位和后4位;对于小于11位数的,比如7位数的电话号码,脱敏方式是显示前2位和后2位。

<div class="content">
    <input
        v-JDesensitization:params="params"
        placeholder="输入需要脱敏的字符"
        class="input-content"
    />
    <div v-JDesensitization:params="params" class="div-content">
        15012345678
    </div>
</div>
<script>
export default{
    data(){
        return {
            params:{
                "config": {
                    "type": "phone",
                    "before": ,
                    "after": "",
                    "ch": "*"
                },
                "fn": ""
            },
        }
    }
}
</script>

身份证号码脱敏

内置有身份证号码的脱敏类型,脱敏方式是显示前3位和后4位;

<div class="content">
    <input
        v-JDesensitization:params="params"
        placeholder="输入需要脱敏的字符"
        class="input-content"
    />
    <div v-JDesensitization:params="params" class="div-content">
        330621199909091234
    </div>
</div>
<script>
export default{
    data(){
        return {
            params:{
                "config": {
                    "type": "idCard",
                    "before": ,
                    "after": "",
                    "ch": "*"
                },
                "fn": ""
            },
        }
    }
}
</script>

姓名脱敏

内置有姓名的脱敏类型,两个字的姓名脱敏方式是显示第1位;大于两个字的姓名脱敏方式是显示第一个字和最后一个字。

<div class="content">
    <input
        v-JDesensitization:params="params"
        placeholder="输入需要脱敏的字符"
        class="input-content"
    />
    <div v-JDesensitization:params="params" class="div-content">
        张三风
    </div>
</div>
<script>
export default{
    data(){
        return {
            params:{
                "config": {
                    "type": "name",
                    "before": ,
                    "after": "",
                    "ch": "*"
                },
                "fn": ""
            },
        }
    }
}
</script>

邮箱脱敏

内置有邮箱的脱敏类型,脱敏方式是显示第一位和@及以后的字符。

<div class="content">
    <input
        v-JDesensitization:params="params"
        placeholder="输入需要脱敏的字符"
        class="input-content"
    />
    <div v-JDesensitization:params="params" class="div-content">
        123456@163.com
    </div>
</div>
<script>
export default{
    data(){
        return {
            params:{
                "config": {
                    "type": "email",
                    "before": ,
                    "after": "",
                    "ch": "*"
                },
                "fn": ""
            },
        }
    }
}
</script>

自定义脱敏

可以自定义脱敏代替字符,默认为*

修改 config 中的 ch 参数即可自定义脱敏代替字符

params: {
    config: {
        type: "phone",
        before: "",
        after: "",
        ch: "~",
    },
    fn: "",
}

可以自定义脱敏字符头尾显示位数

修改 config 中的 before 和 after 参数即可自定义脱敏显示位数,type 需要修改为内置类型以外的,直接传空即可。

params: {
    config: {
        type: "",
        before: "2",
        after: "2",
        ch: "~",
    },
    fn: "",
}

可以自定义脱敏函数进行脱敏

可以直接在参数的 fn 中传入一个脱敏函数,如果传入了 fn,其优先级最高,则其他参数都不会生效,会直接调用传入的 fn函数 进行脱敏,如:

(str) => {
  return str[0] + '@'.repeat(str.length - 1);
}

应用场景

用户信息填写,输入框聚焦时显示真实数据供用户进行修改,失焦时显示脱敏后的数据

(至于为什么会有这个场景,需要去问一下产品经理)

到此这篇关于基于JavaScript实现一个动态脱敏指令的文章就介绍到这了,更多相关JavaScript动态脱敏指令内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 纯JS实现弹性导航条效果

    纯JS实现弹性导航条效果

    本文主要介绍了纯JS实现弹性导航条效果的实例,具有很好的参考价值。下面跟着小编一起来看下吧
    2017-03-03
  • ajax java 实现自动完成功能

    ajax java 实现自动完成功能

    都知道百度建议是用ajax做的,想要做的快速稳定,可复制可移植就不容易了,花时间研究还不如自己来写。根据一个pdf文档提供的资料,用了小半天时间,终于实现了。在此与大家分享
    2012-12-12
  • Array的push与unshift方法性能比较分析

    Array的push与unshift方法性能比较分析

    Array的push与unshift方法都能给当前数组添加元素,不同的是,push是在末尾添加,而unshift则是在开头添加。
    2011-03-03
  • JavaScript Array对象使用方法解析

    JavaScript Array对象使用方法解析

    这篇文章主要介绍了JavaScript Array对象使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • JavaScript制作游戏摇杆方向盘

    JavaScript制作游戏摇杆方向盘

    本文主要介绍了JavaScript制作游戏摇杆方向盘,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2014-04-04
  • Emberjs 通过 axios 下载文件的方法

    Emberjs 通过 axios 下载文件的方法

    这篇文章主要介绍了Emberjs 通过 axios 下载文件的方法,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-09-09
  • JavaScript Proxy基本用法详解

    JavaScript Proxy基本用法详解

    这篇文章主要介绍了JavaScript Proxy基本用法,Proxy对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义,如属性查找、赋值、枚举、函数调用等
    2022-12-12
  • js脚本获取webform服务器控件的方法

    js脚本获取webform服务器控件的方法

    asp.net webform中获取服务器控件,js脚本获取服务器控件需要使用ClientID,下面有个示例,大家可以参考下
    2014-05-05
  • 微信sdk实现禁止微信分享(使用原生php实现)

    微信sdk实现禁止微信分享(使用原生php实现)

    这篇文章主要介绍了微信sdk实现禁止微信分享(使用原生php实现),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • JavaScript 变量作用域分析

    JavaScript 变量作用域分析

    变量作用域是程序中定义这个变量的区域。先贴一段代码,如果读者对代码的输出并不感到困惑就不用往下面读了。
    2011-07-07

最新评论