资讯专栏INFORMATION COLUMN

BASE64编码乱码问题的浅层分析与解释

yacheng / 2106人阅读

摘要:当后端将数据取出再传给前端时,发生了编码混乱的问题。这样的编码错误问题导致数据上的,会造成不良的用户体验。但是,不幸的是,各方对该编码的规则是不同的,这也造成乱码的隐患。

本文由作者朱臻授权网易云社区发布。

1问题案例

曾在开发过程中,我们遇到了BASE64编码乱码的问题,该问题的场景如下:

当web前端,将带有中文字符的字符串base64编码后,传到后端。当后端将数据取出再传给web前端时,发生了编码混乱的问题。例如,当前端向后端传入并保存为"赵俊雅和刘德华的爷爷”字符串后,当需要取出时,取出的字符串是“赵䲺fṤ9b&9occ桹⭹⭀”。这样的编码错误问题导致数据上的bug,会造成不良的用户体验。

2 问题排查

当我们仔细查看该两段字符串时可以发现除了首字符相同,其他字符全部面目全非。这至少可以一定程度说明,字符串在顺序编码或解码中途发生了错误。所以我们将两段字符串分别进行base64编码还原,并进行对比。

6LW15L+K6ZuF5ZKM5YiY5b635Y2O55qE54i354i3(赵俊雅和刘德华的爷爷)

6LW15L K6ZuF5ZKM5YiY5b635Y2O55qE54i354i3(赵䲺fṤ9b&9occ桹⭹⭀)

对比可以看出两者仅有一个+号的区别,后者只是将前者的+替换成空格,这导致除首字母外,后续字母全部发生混乱,因为base64是连续编码,原理将在后面解释。

那为什么会让+编程空格呢?这将从url的规范来解释,我们不难发现前后端交互时,后端会将url都会将+自动转化为空格。这基本上可以解释上述乱码的问题了。

3原理解释:

顺着上述介绍的顺序我们总结下上面提到的几个概念。

3.1BASE64:

它是一种用小规模编码集去表示较大规模编码的方法。本人的理解是:BASE64是指以64为基,存在64种编号的意思。也就是2的6次方=6bit。这64个编码(0~63)分别可以表示 [A~Z] 、[a-z]、[0~9]和[+ 、/]号 。共64种编号。 而与我们熟悉的字节编码对应的是 3*8bit=4*6bit=24bit=2的24次方。根据等式,可以将一切以字节为单位的编码方式(如UTF-8和GBK)转化成 BASE64编码,反之亦然。

也就是将原本3个字节的内容转变成4个BASE字符。这样,从字符角度来讲是变得更长了,扩展成的比例为133%。

3.2URL编码规范:

我们常说的url地址也就是地址栏输入的那串字符串,WWW标准中规定了url中只能包含[0~9,a-z,A-Z]和一些特殊字符$-_.+!*"(),。而我们常用的汉字以及阿拉伯文,拉丁文等都不包含在该范围内,所以必须经过一定规则的编码才能被正确的传输。虽然说浏览器一般都带有自动转码功能,这样使得用户常常感觉不到这一规则的存在。但是,不幸的是,各方对该编码的规则是不同的,这也造成乱码的隐患。Chrome使用utf8,javascript使用unicode,ie采用系统默认编码方式如GB2312。另外一件非常值得注意的事情,浏览器向后端发送URL的时候会自动将 空格替换成+号,这在我们使用google查询的get方法时会明显看到。 query中的中文变成 %XXX,空格变成+。当后端接收到请求后会将URL中的+自动替换成空格。这就是困扰我们多时的BASE64编码乱码给我们带来的一个麻烦。

3.3encodeURIComponent():

该js的方法是前端常用的一种URL处理方式,该种方式结合了过去escape()和encodeURI()两种方法的优势,前者已经很少被使用了,严格的说前者并不是一种专门解决URL编码的方法,只是用于将字符进行unicode编码,并且对于“@ * _ + - . /”等特殊字符并没有做任何处理,这使得其对URL乱码问题并没有很好的解决。而后者encodeURI()实现了全字段的编码,不管是特殊字符还是普通字符编码后都是以utf-8的形式。那主流的encodeURIComponent(),无疑是最佳解决方案,它不会对普通字符编码,只对一些特殊字符进行编码如;/?:@&=+$,# ,这对BASE64是至关重要的。



4可行的解决方案

根据以上特点,我们对当前问题有一些建议性的解决方案。

4.1  对于普通问题直接采用encodeURIComponent() 处理,而BASE64的工作交给后端处理。

4.2 如果有必要在前端做BASE64 可以首先进行BASE64处理,再采用encodeURIComponent() 处理。

4.3 另外,还可以直接使用BASE64的变种,将“+”和“/”两个特殊字符用 URL安全的“-”-和“_”字符处理,当然任何脑洞更大的字符替换也是可以的,现成的方式有safety base64等。

本文只是分享个人处理该问题的经验,如遇错误之处,请各位批评指正,也欢迎各位探讨交流。




更多网易技术、产品、运营经验分享请访问网易云社区。

文章来源: 网易云社区

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/25321.html

相关文章

  • Java程序员遇上字符乱码2-容易混淆两种编码类别

    摘要:字符集编码就是对字符根据不同字符集中对应的格式进行编码解码,这个大家都好理解。下面详细说说,以编码解码和编码解码为例。 《来自罗志晓的笔记:http://note.youdao.com/notesh...》我们平时老说的编码解码,很多人都只知道 字符集编码解码。其实除了字符集编码解码,常见的还有另一类,如 Url编码解码、Base64编码解码。这两类编码的原理是完全不一样的,如果没有了...

    hidogs 评论0 收藏0
  • Base64 JS编码/解码

    摘要:注意点如果所示,上面说到的编码解码方法并不支持中文,因为它们只支持编码。转换编码中文进行转码之后在编码。最优方案在某些情况下,用了上面的方法也会出现中文乱码的情况,如获取到的音乐歌词解析出来的歌词等。 为什么要编码 简单粗暴的解释就是为了数据的安全性。 编码/解码常用方法(仅针对Base64) 编码 我们一般使用 window.btoa() 对原始数据进行编码。 解码 我们一般使用 w...

    why_rookie 评论0 收藏0
  • 你知道前端对图片处理方式吗?

    摘要:对于第二种存储方式,我们前端需要将其二进制流交由对象处理,然后通过的生成临时赋值给属性来显示。当后端返回特定的图片二进制流的时候,就像我第一里的情景再现说的,前端用容器接收。 前言 作为前端工程师 de 我们,日常少不了会跟图片打交道。在各大电商平台工作的前端工程师们,感受可能会更加的明显。 以下是我之前跟图片打交道踩到的坑,跟大家分享一下经验。 一、情景再现 用postman请求接口...

    helloworldcoding 评论0 收藏0
  • 你知道前端对图片处理方式吗?

    摘要:对于第二种存储方式,我们前端需要将其二进制流交由对象处理,然后通过的生成临时赋值给属性来显示。当后端返回特定的图片二进制流的时候,就像我第一里的情景再现说的,前端用容器接收。 前言 作为前端工程师 de 我们,日常少不了会跟图片打交道。在各大电商平台工作的前端工程师们,感受可能会更加的明显。 以下是我之前跟图片打交道踩到的坑,跟大家分享一下经验。 一、情景再现 用postman请求接口...

    LiuRhoRamen 评论0 收藏0

发表评论

0条评论

yacheng

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<