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

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等。

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

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

相关文章:
【推荐】 网易云易盾牵手百视通 助力广电领域新媒体内容安全
【推荐】 数据分析怎么更直观?十分钟构建数据看板

BASE64编码乱码问题的浅层分析与解释的更多相关文章

  1. Tensorflow MNIST浅层神经网络的解释和答复

    本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/51416540 看到之前的一篇博文:深入 ...

  2. 浅谈Base64编码

    浅谈Base64编码 我打赌当你见到Base64这个词的时候你会觉得在哪里见过,因为在你能够上网看到这篇文章的时候你已经在后台使用它了.如果您对二进制数有所了解,你就可以开始读它了. 打开一封Emai ...

  3. 浅谈Base64编码算法

    一.什么是编码解码 编码:利用特定的算法,对原始内容进行处理,生成运算后的内容,形成另一种数据的表现形式,可以根据算法,再还原回来,这种操作称之为编码. 解码:利用编码使用的算法的逆运算,对经过编码的 ...

  4. BASE64编码原理分析脚本实现及逆向案例

    在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理你又了解多少?今天小编带大家了解一下Base64编码原理分析脚本实现及逆向案例的相关内容.   01编码由来 数 ...

  5. Base64编码原理分析

    Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,在了解Base64编码之前,先了解几个基本概念:位.字节. 位:"位(bit)"是计算机中最小的数据单位.每一位 ...

  6. java base64编码 加密和解密(切记注意乱码问题)

    BASE64 编码是一种常用的字符编码,在很多地方都会用到.JDK 中提供了非常方便的 BASE64Encoder 和 BASE64Decoder,用它们可以非常方便的完成基于 BASE64 的编码和 ...

  7. 一篇文章彻底弄懂Base64编码原理

    在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理又了解多少?今天这篇博文带领大家了解一下Base64的底层实现. Base64的由来 目前Base64已经成为网 ...

  8. Delphi 读取 c# webservice XML的base64编码图片字符串转化图片并显示

    Delphi 读取 c# webservice XML的base64编码图片字符串转化图片并显示 在 开发中遇到应用c#及asp.net的在的webservice 保存图片并以xml文件形式现实出来 ...

  9. 一篇文章彻底弄懂Base64编码原理(转载)

    在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理又了解多少?今天这篇博文带领大家了解一下Base64的底层实现. Base64的由来 目前Base64已经成为网 ...

随机推荐

  1. leetcode73

    public class Solution { public void SetZeroes(int[,] matrix) { ); ); var listrow = new Dictionary< ...

  2. Android bitmap转byte

    逆转start协议输出 private static byte[] bitmap2byte(Bitmap bmp) throws Exception{ return bitmap2byte(bmp, ...

  3. localStorage,sessionStorage

    h5的本地存储. 现代浏览器普遍开始支持H5本地存储,localStorage.sessionStorage.可以用来代替cookie的一部分存储功能,他比cookie存储量更大.比较实用. 两者用法 ...

  4. 如何使用find命令在Linux中查找文件

    Linux Find命令是Linux系统管理员工具库中最强大的工具之一. Find是一个命令行实用程序,它允许您根据用户给定的表达式搜索目录层次结构中的文件和目录,并对每个匹配的文件应用用户指定的操作 ...

  5. What I'm Researching

    [What I'm Researching] 1.C++11 2.NLP 3.android dev 4.warm up 5.PageRank

  6. 2015年传智播客JavaEE 第168期就业班视频教程17-登录功能业务逻辑实现(代码)

    点击红色在业务层接口EmpEbi创建方法login 按F4弹出类继承层次视图 这些快捷键是条件反射了. 业务层做MD5数据加密,不能放在表现层也不能放在数据层必须放在业务层.它属于业务操作. 数据层的 ...

  7. Python slice() 函数

    Python slice() 函数  Python 内置函数 描述 slice() 函数实现切片对象,主要用在切片操作函数里的参数传递. 语法 slice 语法: class slice(stop) ...

  8. 把二叉搜索树转化成更大的树 · Convert BST to Greater Tree

    [抄题]: 给定二叉搜索树(BST),将其转换为更大的树,使原始BST上每个节点的值都更改为在原始树中大于等于该节点值的节点值之和(包括该节点). Given a binary search Tree ...

  9. [udemy]WebDevelopment_Bootstrap,Templates

    Bootstrap Introduction Bootstrap 相对于CSS, JS 就像PPT模板相对于PPT 说白了就是前人已经做好了(pre-build)很多模板,你可以直接拿来主义 Boot ...

  10. Introduction Sockets to Programming in C using TCP/IP

    Introduction Computer Network: hosts, routers, communication channels Hosts run applications Routers ...