2023.8.17 星期四
基础
decodeURIComponent解码数据丢失
含有特殊符%25等特殊字符时decode会丢失字符。
URL中的保留和不安全字符
所谓保留字符就是那些在URL中具有特定意义的字符。不安全字符是指那些在URL中没有特殊含义,但在URL所在的上下文中可能具有特殊意义的字符。例如双引号(“”)
部分保留字符和不安全字符及其URL编码
字符 | 描述 | 用法 | 编码
– | -| - | -
; | 分号 | 保留 | %3B
/ | 斜线 | 保留 | %2F
? | 问号 | 保留 | %3F
: | 冒号 | 保留 | %3A
@ | “at”符号 | 保留 | %4O
= | 等号 | 保留 | %3D
& | “和”符号 | 保留 | %26
< | 小于号 | 不安全 | %3C
> | 大于号 | 不安全 | %3E
“ | 双引号 | 不安全 | %22
# | 井号 | 不安全 | %23
% | 百分号 | 不安全 | %25
{ | 左大括号 | 不安全 | %7B
} | 右大括号 | 不安全 | %7D
| | 竖线 | 不安全 | %7C
\ | 反斜线 | 不安全 | %5C
^ | 加字号 | 不安全 | %5E
~ | 波浪 | 不安全 | %7E
[ | 左中括号 | 不安全 | %5B
] | 右中括号 | 不安全 | %5D
` | 反单引号 | 不安全 | %60
| 空格 | 不安全 | %20
案例一
例如:
http://abaaba.com/example/file-upload/file/shendeng%25-%25bal20bablabla.pdf
这种带特殊符(%25)的链接经过解码后,数据会丢失(25消失不见了)
解决方案:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// 对查询关键字中的特殊字符进行编码
dealURISafely(key) {
const unsafeStr = [{
code: '%',
encode: '%25'
}, {
code: '{',
encode: '%7B'
}, {
code: '}',
encode: '%7D'
}, {
code: '#',
encode: '%23'
}// 简单举例
];
return key.replace(/[%?#&=]/g, ($, index, str) => { // 匹配替换
for (const item of unsafeStr) {
if (item.code === $) {
return item.encode;
}
}
});
}
案例二
有时,浏览器也会帮我们编译字符,如:
https://baidu.com/%E7%A5%9E%E7%81%AF%E4%B8%AA%E4%BA%BA%E6%A6%9C%E5%89%8D10%
用decodeURIComponent解码会报错。
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// 解决方案一
// 简单粗暴的用tryCatch去检测,异常直接跳出!
dealURISafely(uri) {
try {
return decodeURIComponent(uri)
} catch(e) {
console.log('Uncaught URIerror' + uri)
return uri
}
}
// 如果这样的方法过于粗暴,没有解决问题~ 那我们可以尝试下面的更细致一些的方法~
// 解决方案二
dealURISafely(uri, mod = 0) {
let decodeStr = '';
const dealUri = uri.split(/(%(?:d0|d1)%.{2})/);
for (let i = 0; i < dealUri.length; i++) {
try {
const decoded = decodeURIComponent(dealUri[i]);
decodeStr += decoded;
} catch (e) {
if (mod) {
const replaced = dealUri[i].replace(/%(?!\d+)/g, '%25');
decodeStr += replaced;
} else {
decodeStr += dealUri[i];
}
}
}
return decodeStr;
} // "https://baidu.com/神灯个人榜前10% "