Apifox 学习笔记 - 后置操作 - 脱敏

Posted 笑虾

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Apifox 学习笔记 - 后置操作 - 脱敏相关的知识,希望对你有一定的参考价值。

Apifox 学习笔记 - 后置操作 - 脱敏

后置操作

因为脱敏 这个功能,很多接口都会用到,所以放到公共脚本

替换星号

substr 实现

substr 未来将可能会被移除掉,应避免使用。

var idCard = `433101202212310123`;
var head=6, tail=-4;
// 如要有需要也可以固定 * 的个数
idCard = idCard.substr(0, head)+ '*'.repeat(idCard.length-10) +idCard.substr(tail);
console.info(idCard); // 433101********0123

substring 实现

substring

var idCard = `433101202212310123`;
var head=6, tail=4;
idCard = `$idCard.substring(0,head)********$idCard.substring(idCard.length-tail, idCard.length)`; // 开头6个,末尾4个字符。
console.info(idCard); // 433101********0123

replace 实现

replace 替换固定长度个 *

 d.phone.replace(/^(.3)(.*)(.4)$/, `$1****$3`);

replace 升级版:保留开头、结尾,替换其他部分。

var idCard = `433101202212310123`;
var head=6, tail=5;
var pattern = new RegExp(`^(.$head)(.*)(.$tail)$`);
var replacer = (m, p1, p2, p3) => `$p1$'*'.repeat(p2.length)$p3`;

idCard = idCard.replace(pattern, replacer);
console.info(idCard); 

封装成方法

/**
 * 默认保留开头1个字符,结尾1个字符,其他替换为*星号
 */
function desensitize(head=1, tail=1, padding='*')
	let regexp = new RegExp(`(.$head)(.*)(.$tail)`);
	return this.replace(regexp, (m, p1, p2, p3) => `$p1$padding.repeat(p2.length)$p3`);

String.prototype.desensitize = desensitize;
var idCard = `433101202212310123`;
idCard.desensitize(6, 4, '#'); // 433101########0123

脱敏方案

基础版本

已知接口有统一返回格式,一个简单的替换方案如下:


	code: 200,
	msg: "操作成功",
	data: [
		name: "笑虾", phone: "18966668888", idCard: "433101200612310123"
	]

var jsonData = pm.response.json();

jsonData.data = jsonData.data.map(d => 
    // 电话
    d.phone = d.phone.replace(/^(.3)(.*)(.4)$/, `$1****$3`);
    // 身份证
    d.idCard = d.idCard.split('').map((v, i) => i >= 5 && i <= 13 ? '*' : v).join('');
    // 姓名
    d.name = d.name[0] + '*'.repeat(d.name.length - 1);
    return d;
);

pm.response.setBody(jsonData);

手动定位版本

如果接口有统一返回格式。适用于这种。给了默认的data位置,如果想自定义也可以传个 lambda 进来取 data

  1. 根目录后置操作中添加公共脚本-脱敏Util。替换字段串的公用逻辑。
  2. 根目录后置操作中添加公共脚本-脱敏-标准响应格式。针对标准响应格式的通用处理代码。
  3. 接口后置操作中添加自定义脚本。当通用处理无法满足某些接口时,使用自定义脚本定义key获取data的方法。

公共脚本-脱敏Util

tm 方法定义为全局变量,就可以在其它脚本中调用了。

// 替换字符串
String.prototype.doDesensitize = function () 
    var len = Math.ceil(this.length / 3);
    return this.replace(new RegExp(`(.$len)(.+)`), `$1$'*'.repeat(this.length - len)`);

// 遍历给定的 key 逐个替换
function desensitize(data, arr) 
    return data.map(d => 
        arr.forEach(key => 
            if (d[key]) 
                d[key] = d[key].doDesensitize();
            
        );
        return d;
    );

/**
 * arr          需要脱敏的字段
 * lambdaFun    获取需要脱敏的数据的 lambda
 */
tm = function(arr = ['phone', 'idCard', 'name'], lambdaFun = json => json.data) 
    var jsonData = pm.response.json(); // 从响应中取出原数据
    var tmData = lambdaFun(jsonData);  // 脱敏数据在响应中的位置
    jsonData.data = desensitize(tmData, arr);   // 数据脱敏
    return jsonData;

通用版

通用版遍历给定对象的所有key对目标进行脱敏。相对来说需要消耗更多资源。

公共脚本-脱敏-递归遍历所有key

/**
 * 获取脱敏结果
 * 
 * @param keyList 待处理列表记录了哪些 key 对应的值需要脱敏处理
 * @param jsonObject 待脱敏的原始数据
 */
desensitize = function(arr, jsonObject) 
	// ------------- 初始化参数 -------------
	var keyList = arr || ['phone', 'idCard', 'name'];
	try
	    var jsonData = jsonObject || pm.response.json();
	catch(e)
	    console.log(e.message);
	
	
	// ------------- 业务逻辑 -------------
	/**
	 * 处理 key
	 * @param key 待处理的key
	 */
	function processKey(k) return k;
	
	/**
	 * 处理 value
	 * 将字符串的后 2/3 替换为星号
	 * @param value 待处理的value
	 */
	function processValue(v) 
		var len = Math.ceil(v.length / 3);
		return v.replace(new RegExp(`(.$len)(.+)`), `$1$'*'.repeat(v.length - len)`);
	

	/**
	 * 累加处理键值对的方法	
	 * 
	 * @param resultObj 之前步骤处理的结果累积。
	 */
	function reducer(resultObj, [currentKey, currentValue]) 
		// 如果是对象递归解析
		if (typeof currentValue === "object") 
			return  ...resultObj, [currentKey]: recursionFn(currentValue) ;
		
		// 待处理列表中包含的key,对 key、value 进行处理(脱敏)
		if (keyList.includes(currentKey)) 
			return  ...resultObj, [processKey(currentKey)]: processValue(currentValue) ;
		
		return  ...resultObj, [currentKey]: currentValue ;
	
		
	/**
	 * 递归遍历所有键值对。对keyList包含的key的值进行脱敏。
	 * 
	 * @param targetObj 待处理的原对象
	 */
	function recursionFn(targetObj) 
		// console.log(targetObj);
		// 如果是数组,对每个元素调用递归处理函数
		if (Array.isArray(targetObj)) 
			return targetObj.map(v => recursionFn(v));
		
		// 否则:累加处理键值对。累加结果初始为 
		return Object.entries(targetObj).reduce(reducer, );
	

	// 从响应中取出原数据,脱敏,返回
	return recursionFn(jsonData); 

自定义脚本

对有特殊需求的接口可以自定义需要处理的key

var arr = ['phone', 'idCard', 'name', 'address','social','legal','person'];
var responseBody = desensitize(arr);
pm.response.setBody(responseBody);

在浏览器控制台临时使用

var jsonData = ; // 这个就是要脱敏的数据
var arr = ['phone', 'idCard', 'name', 'address','social','legal','person', 'company'];
var result = desensitize(arr, jsonData);
copy(result);
console.log(result);

参考资料

笑虾:JS 正则笔记
笑虾:JavaScript 递归的几种写法
MDN:String.prototype.replace()

以上是关于Apifox 学习笔记 - 后置操作 - 脱敏的主要内容,如果未能解决你的问题,请参考以下文章

Apifox 学习笔记 - 后置操作 - 脱敏

Apifox 学习笔记 - 前置操作

Apifox 学习笔记 - 前置操作

apifox接口文档怎么返回响应json对象

如何优雅的实现数据脱敏

效率神器Apifox_API 文档API 调试API MockAPI 自动化测试工具推荐