使用TypeScript和裝飾器實(shí)現(xiàn)前端數(shù)據(jù)脫敏
一、需求背景
雖然我經(jīng)常在很多地方都說過,“前端脫敏,脫褲子放屁。”
但在用戶需要截圖,或者是數(shù)據(jù)極其敏感的情況下,不管后端是否脫敏,前端都還是應(yīng)該給人脫敏一下的。
否則用戶截圖的話,就需要先截圖,再用截圖工具抹掉敏感信息后再發(fā)送,如果是極其敏感的數(shù)據(jù)的話。
所以需求來了:
要求在前端表格中的所有敏感數(shù)據(jù)列都需要脫敏,且需要支持用戶點(diǎn)擊查看原始數(shù)據(jù)。
二、需求目標(biāo)
2.1 實(shí)現(xiàn)效果

2.2 如何使用

2.3 自定義脫敏
只需要在需要脫敏的屬性上的 @Table() 裝飾器中配置脫敏方式即可。當(dāng)然,也支持直接自定義脫敏:

實(shí)現(xiàn)的效果就這樣咯:

三、實(shí)現(xiàn)過程
3.1 @Table參數(shù)聲明
我們需要在負(fù)責(zé)管理表格狀態(tài)的 @Table() 裝飾器的參數(shù)中添加下面一些如 2.3 截圖中的配置項(xiàng):
3.1.1 desensitize 脫敏類型
配置這個(gè)后才能自動(dòng)脫敏,該配置是個(gè)枚舉選項(xiàng):
static TELEPHONE = new AirDesensitizeType(0, '座機(jī)號(hào)碼', 3, 4) static MOBILE = new AirDesensitizeType(1, '手機(jī)號(hào)碼', 3, 4) static ID_CARD = new AirDesensitizeType(2, '身份證號(hào)', 6, 4) static BANK_CARD = new AirDesensitizeType(3, '銀行卡號(hào)', 4, 4) static CAR_NUMBER = new AirDesensitizeType(4, '車牌號(hào)', 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)
其中,末尾的兩個(gè)數(shù)字代表脫敏的頭部保留數(shù)量和尾部保留數(shù)量。
3.1.2 desensitizeHead
脫敏開始保留的數(shù)量,默認(rèn)為0,可覆蓋 3.1.1 中的 倒數(shù)第二 個(gè)參數(shù)。
3.1.3 desensitizeTail
脫敏結(jié)尾保留的數(shù)量,默認(rèn)為0,可覆蓋 3.1.1 中的 倒數(shù)第一 個(gè)參數(shù)。
3.1.4 desensitizeSymbol
脫敏符號(hào),默認(rèn)為 *。
3.2 編寫脫敏助手類
我們定義了一個(gè) AirDesensitize 助手類,用于實(shí)現(xiàn)脫敏邏輯。
/**
* # 脫敏助手類
*
* @author Hamm.cn
*/
export class AirDesensitize {
/**
* ## `IPv4` 的塊長(zhǎng)度
*/
private static readonly IP_V4_PART_COUNT = 4
/**
* ## 字符串替換
*
* @param text 原始字符串
* @param head 頭部保留長(zhǎng)度
* @param tail 尾部保留長(zhǎng)度
* @param symbol 中間替換的單個(gè)符號(hào)
* @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 [可選]符號(hào)
* @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 脫敏符號(hào)
* @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:
// 包含區(qū)號(hào) 前后各留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>
我們添加一個(gè) v-if 來判斷是否需要脫敏,然后使用 AirDesensitize 助手類提供的 desensitize 方法來脫敏即可。
好的,搞定!
接下來其他同事就只需要美滋滋的去給屬性的 @Table() 裝飾器標(biāo)參數(shù)即可~
到此這篇關(guān)于使用TypeScript和裝飾器實(shí)現(xiàn)前端數(shù)據(jù)脫敏的文章就介紹到這了,更多相關(guān)TypeScript數(shù)據(jù)脫敏內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript判斷變量是否為undefined的兩種寫法區(qū)別
這篇文章主要是對(duì)JavaScript判斷變量是否為undefined的兩種寫法區(qū)別進(jìn)行了詳細(xì)的介紹,需要的朋友可以過來參考下,希望對(duì)大家有所幫助2013-12-12
JavaScript獲取客戶端計(jì)算機(jī)硬件及系統(tǒng)等信息的方法
本文為大家詳細(xì)介紹下如何使用JavaScript獲取客戶端計(jì)算機(jī)硬件及系統(tǒng)等信息,下面有個(gè)不錯(cuò)的示例,感興趣的朋友可以參考下2014-01-01
JavaScript基于面向?qū)ο髮?shí)現(xiàn)的猜拳游戲
這篇文章主要介紹了JavaScript基于面向?qū)ο髮?shí)現(xiàn)的猜拳游戲,結(jié)合完整實(shí)例形式分析了javascript基于面向?qū)ο髮?shí)現(xiàn)猜拳游戲的具體頁(yè)面布局、樣式及功能相關(guān)操作技巧,需要的朋友可以參考下2018-01-01
前端頁(yè)面適配之postcss-px-to-viewport實(shí)現(xiàn)步驟
postcss-px-to-viewport是一個(gè)PostCSS插件,它可以將px單位轉(zhuǎn)換為視口單位(vw、vh?或?vmin),這篇文章主要給大家介紹了關(guān)于前端頁(yè)面適配之postcss-px-to-viewport的實(shí)現(xiàn)步驟,需要的朋友可以參考下2024-03-03
原生JS實(shí)現(xiàn)列表內(nèi)容自動(dòng)向上滾動(dòng)效果
這篇文章主要介紹了原生JS實(shí)現(xiàn)列表內(nèi)容自動(dòng)向上滾動(dòng)效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05
Web層改進(jìn)II-用xmlhttp 無聲息提交復(fù)雜表單
Web層改進(jìn)II-用xmlhttp 無聲息提交復(fù)雜表單...2007-01-01
Ajax實(shí)現(xiàn)郵箱驗(yàn)證實(shí)例代碼
這篇文章介紹了Ajax實(shí)現(xiàn)郵箱驗(yàn)證的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04
JavaScript中不冒泡的DOM事件的使用小結(jié)
本文主要介紹了JavaScript中不冒泡的DOM事件的使用小結(jié),包括常見的focus、blur、load、unload等事件,并提供了解決方案,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2026-03-03

