起因:

前端的传值在控件和控制台在以肉眼看来并没有什么问题,但后端收到的值却多出了一些特殊字符(\u200b),导致后端处理数据失败;
效果图

了解零宽字符 - \u200b

经查询之后发现 \u200b 是零宽字符系列中的一个,零宽字符是一种不可打印的 Unicode 字符;

零宽字符主要有以下几类:

零宽度空格符 (zero-width space) U+200B : 用于较长单词的换行分隔;
零宽度非断空格符 (zero width no-break space) U+FEFF : 用于阻止特定位置的换行分隔;
零宽度连字符 (zero-width joiner) U+200D : 用于阿拉伯文与印度语系等文字中,使不会发生连字的字符间产生连字效果;
零宽度断字符 (zero-width non-joiner) U+200C : 用于阿拉伯文,德文,印度语系等文字中,阻止会发生连字的字符间的连字效果;
左至右符 (left-to-right mark) U+200E : 用于在混合文字方向的多种语言文本中(例:混合左至右书写的英语与右至左书写的希伯来语),规定排版文字书写方向左至右;
右至左符 (right-to-left mark) U+200F : 用于在混合文字方向的多种语言文本中,规定排版文字书写方向为右至左;

溯源

测试人员复制的丰声聊天框里面的数据(怀疑是不是一种隐形水印的做法?)然后在前端组件中粘贴输入,提交之后发现出现了‘\u200b’的字符;

如何处理

  1. 后端接收时处理
  2. 前端输入时处理(input inputText)类似 falsyParamsFilter 函数
1
2
3
4
5
6
const formatData = (data: string) =>
data
.split(/,|,/g)
.map((i: string) => i.replace(/^\s*|\s*$|\s*\u200B/g, ''))
.filter((i: string) => !!i)
.join(',');

更多有趣的事情

  1. 颜文字 象形字 图像 icon
    eg: ‘\ud83d\udeeb’ (飞机) %28\u0e51\u203e \ua1f4 \u203e\u0e51%29 (๑‾ ꇴ ‾๑)
  2. 隐形水印、加密解密
  3. 存储隐藏信息

隐形水印

https://github.com/umpox/zero-width-detection

加密 解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// 每个字符转为二进制,用空格分隔
const textToBinary = (username) =>
username
.split('')
// charCodeAt 将字符转成相应的 Unicode 码值
.map((char) => char.charCodeAt(0).toString(2))
.join(' ');

const binaryToZeroWidth = (binary) =>
binary
.split('')
.map((binaryNum) => {
const num = parseInt(binaryNum, 10);
if (num === 1) {
return '\u200b'; // \u200b 零宽度字符(zero-width space)
} else if (num === 0) {
return '\u200c'; // \u200c 零宽度断字符(zero-width non-joiner)
}
return '\u200d'; // \u200d 零宽度连字符 (zero-width joiner)
})
.join('\ufeff'); // \ufeff 零宽度非断空格符 (zero width no-break space)

const encode = (username) => {
const binaryUsername = textToBinary(username);
const zeroWidthUsername = binaryToZeroWidth(binaryUsername);
return zeroWidthUsername;
};

const zeroWidthToBinary = (string) =>
string
.split('\ufeff')
.map((char) => {
// \ufeff 零宽度非断空格符 (zero width no-break space)
if (char === '\u200b') {
// \u200b 零宽度字符(zero-width space)
return '1';
} else if (char === '\u200c') {
// \u200c 零宽度断字符(zero-width non-joiner)
return '0';
}
return ' ';
})
.join('');

const binaryToText = (string) =>
// fromCharCode 二进制转化
string
.split(' ')
.map((num) => String.fromCharCode(parseInt(num, 2)))
.join('');

const decode = (zeroWidthUsername) => {
const binaryUsername = zeroWidthToBinary(zeroWidthUsername);
const textUsername = binaryToText(binaryUsername);
return textUsername;
};
效果图

excel 中不可见字符,excel 里最隐蔽的坑

https://www.office26.com/excelhanshu/excel_function_11341.html

参考文献:
https://www.cnblogs.com/goodAndyxublog/p/13383519.html
https://www.jianshu.com/p/64580eb7e9ad
https://juejin.cn/post/6844903902220042254
https://zh.wikipedia.org/wiki/%E9%9B%B6%E5%AE%BD%E7%A9%BA%E6%A0%BC