使用TypeScript和装饰器实现前端数据脱敏

 更新时间:2024年11月19日 08:45:39   作者:Hamm  
这篇文章主要为大家详细介绍了如何使用TypeScript和装饰器实现前端数据脱敏功能,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下

一、需求背景

虽然我经常在很多地方都说过,“前端脱敏,脱裤子放屁。”

但在用户需要截图,或者是数据极其敏感的情况下,不管后端是否脱敏,前端都还是应该给人脱敏一下的。

否则用户截图的话,就需要先截图,再用截图工具抹掉敏感信息后再发送,如果是极其敏感的数据的话。

所以需求来了:

要求在前端表格中的所有敏感数据列都需要脱敏,且需要支持用户点击查看原始数据。

二、需求目标

2.1 实现效果

2.2 如何使用

2.3 自定义脱敏

只需要在需要脱敏的属性上的 @Table() 装饰器中配置脱敏方式即可。当然,也支持直接自定义脱敏:

实现的效果就这样咯:

三、实现过程

3.1 @Table参数声明

我们需要在负责管理表格状态的 @Table() 装饰器的参数中添加下面一些如 2.3 截图中的配置项:

3.1.1 desensitize 脱敏类型

配置这个后才能自动脱敏,该配置是个枚举选项:

  static TELEPHONE = new AirDesensitizeType(0, '座机号码', 3, 4)
  static MOBILE = new AirDesensitizeType(1, '手机号码', 3, 4)
  static ID_CARD = new AirDesensitizeType(2, '身份证号', 6, 4)
  static BANK_CARD = new AirDesensitizeType(3, '银行卡号', 4, 4)
  static CAR_NUMBER = new AirDesensitizeType(4, '车牌号', 2, 1)
  static EMAIL = new AirDesensitizeType(5, '邮箱', 2, 2)
  static CHINESE_NAME = new AirDesensitizeType(6, '中文名', 1, 1)
  static ADDRESS = new AirDesensitizeType(7, '地址', 3, 0)
  static IP_V4 = new AirDesensitizeType(8, 'IPv4地址', 0, 0)
  static CUSTOM = new AirDesensitizeType(9, '自定义', 0, 0)

其中,末尾的两个数字代表脱敏的头部保留数量和尾部保留数量。

3.1.2 desensitizeHead

脱敏开始保留的数量,默认为0,可覆盖 3.1.1 中的 倒数第二 个参数。

3.1.3 desensitizeTail

脱敏结尾保留的数量,默认为0,可覆盖 3.1.1 中的 倒数第一 个参数。

3.1.4 desensitizeSymbol

脱敏符号,默认为 *

3.2 编写脱敏助手类

我们定义了一个 AirDesensitize 助手类,用于实现脱敏逻辑。

/**
 * # 脱敏助手类
 *
 * @author Hamm.cn
 */
export class AirDesensitize {
  /**
   * ## `IPv4` 的块长度
   */
  private static readonly IP_V4_PART_COUNT = 4

  /**
   * ## 字符串替换
   *
   * @param text   原始字符串
   * @param head   头部保留长度
   * @param tail   尾部保留长度
   * @param symbol 中间替换的单个符号
   * @return 替换后的字符串
   */
  public static replace(text: string, head: number, tail: number, symbol: string): string {
    if (head < 0 || tail < 0 || head + tail >= text.length) {
      return text
    }
    let str = ''
    for (let i = 0; i < text.length; i += 1) {
      if (i >= head && i <= text.length - tail - 1) {
        str += symbol
      } else {
        str += text[i]
      }
    }
    return str
  }

  /**
   * ## `IPv4` 地址脱敏
   *
   * @param ipv4   `IPv4` 地址
   * @param symbol [可选]符号
   * @return 脱敏后的 `IPv4` 地址
   */
  public static desensitizeIpv4Address(ipv4: string, symbol = AirConstant.ASTERISK): string {
    const strings = ipv4.split(AirConstant.DOT)
    if (strings.length !== AirDesensitize.IP_V4_PART_COUNT) {
      return ipv4
    }
    const temp = symbol + symbol + symbol
    strings[1] = temp
    strings[2] = temp
    return strings.join(AirConstant.DOT)
  }

  /**
   * ## 文本脱敏
   *
   * @param valueString 原始文本
   * @param type        脱敏类型
   * @param head        头部保留
   * @param tail        尾部保留
   * @param symbol      脱敏符号
   * @return 脱敏后的文本
   */
  public static desensitize(valueString: string, type: AirDesensitizeType, head = 0, tail = 0, symbol = AirConstant.ASTERISK): string {
    switch (type.key) {
      case AirDesensitizeType.BANK_CARD.key:
      case AirDesensitizeType.ID_CARD.key:
      case AirDesensitizeType.MOBILE.key:
      case AirDesensitizeType.ADDRESS.key:
      case AirDesensitizeType.CAR_NUMBER.key:
      case AirDesensitizeType.EMAIL.key:
        head = Math.max(type.head, head)
        tail = Math.max(type.tail, tail)
        break
      case AirDesensitizeType.IP_V4.key:
        return AirDesensitize.desensitizeIpv4Address(valueString, symbol)
      case AirDesensitizeType.CHINESE_NAME.key:
        head = Math.max(type.head, head)
        tail = Math.max(type.tail, tail)
        if (valueString.length <= head + tail) {
          tail = 0
        }
        break
      case AirDesensitizeType.TELEPHONE.key:
        // 包含区号 前后各留4 不包含则各留2
        // eslint-disable-next-line no-case-declarations
        const isContainRegionCode = valueString.length > 8 ? 4 : 2
        head = Math.max(isContainRegionCode, head)
        tail = Math.max(isContainRegionCode, tail)
        break
      default:
    }
    return this.replace(valueString, head, tail, symbol)
  }
}

3.3 给表格组件添加脱敏逻辑

<el-table-column>
  <!-- ...省略... -->
  <template v-if="columnConfig.desensitize">
    {{ AirDesensitize.desensitize(getColumnRowData(row), columnConfig.desensitize, columnConfig.desensitizeHead, columnConfig.desensitizeTail, columnConfig.desensitizeSymbol) }}
  </template>
  <template v-else>
    getColumnRowData(row)
  </template>
  <!-- ...省略...  -->
</el-table-column>

我们添加一个 v-if 来判断是否需要脱敏,然后使用 AirDesensitize 助手类提供的 desensitize 方法来脱敏即可。

好的,搞定!

接下来其他同事就只需要美滋滋的去给属性的 @Table() 装饰器标参数即可~

到此这篇关于使用TypeScript和装饰器实现前端数据脱敏的文章就介绍到这了,更多相关TypeScript数据脱敏内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • webpack动态加载与打包方式

    webpack动态加载与打包方式

    webpack有两种组织模块依赖的方式,同步和异步,这篇文章主要介绍了webpack动态加载与打包方式,本文结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • JS正则表达式实现字符串中连续在一起的字符去重

    JS正则表达式实现字符串中连续在一起的字符去重

    这篇文章主要给大家介绍了关于JS正则表达式实现字符串中连续在一起的字符去重的相关资料,学会正则表达式对开发者而言是个非常有用的技能,很多功能可以简单的用一句正则来实现,需要的朋友可以参考下
    2023-11-11
  • 通过示例彻底搞懂js闭包

    通过示例彻底搞懂js闭包

    下面小编就为大家带来一篇通过示例彻底搞懂js闭包。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • PHP自动加载autoload和命名空间的应用小结

    PHP自动加载autoload和命名空间的应用小结

    PHP的自动加载就是我们加载实例化类的时候,不需要手动去写require来导入这个class.php文件,程序自动帮我们加载导入进来这.篇文章主要介绍了PHP自动加载autoload和命名空的应用,需要的朋友可以参考下
    2017-12-12
  • 前端HTTP发POST请求携带参数与后端接口接收参数的实现

    前端HTTP发POST请求携带参数与后端接口接收参数的实现

    近期在学习的时候,碰到一个关于post的小问题,故拿出来分享一下,下面这篇文章主要给大家介绍了关于前端HTTP发POST请求携带参数与后端接口接收参数的相关资料,需要的朋友可以参考下
    2022-10-10
  • 10个JavaScript中易犯小错误

    10个JavaScript中易犯小错误

    10个JavaScript中易犯小错误,需要大家注意!
    2016-02-02
  • JS中的进程和线程详解

    JS中的进程和线程详解

    进程和线程都是计算机中的概念,用于描述程序执行时的运行单位。在 JavaScript 中,进程和线程的概念并不是直接暴露给开发者的,而是通过浏览器或 Node.js 等执行环境来实现的,文中介绍的非常详细,感兴趣的同学可以阅读一下
    2023-04-04
  • JavaScript之Date_动力节点Java学院整理

    JavaScript之Date_动力节点Java学院整理

    在JavaScript中,Date对象用来表示日期和时间。下面给大家介绍js中的date,需要的朋友参考下吧
    2017-06-06
  • 前端JS,删除JSON数据(JSON数组)中的指定元素方式

    前端JS,删除JSON数据(JSON数组)中的指定元素方式

    这篇文章主要介绍了前端JS,删除JSON数据(JSON数组)中的指定元素方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • Javascript 作用域使用说明

    Javascript 作用域使用说明

    在传统的面向对象程序设计中,主要关注于公用和私有作用域。公用作用域中的对象属性可以从对象外部访问,即开发者创建对象的实例后,就可使用它的公用属性。
    2009-08-08

最新评论