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

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. ES6系列_8之函数和数组

    1.对象的函数解构 ES6为我们提供了这样的解构赋值使在前后端分离时,后端返回来JSON格式的数据,前端可以直接把这个JSON格式数据当作参数,传递到函数内部进行处理.比如: let json = { ...

  2. 新的方法(Set<T>)实现mvc的crud

    model层的属性为: public partial class UserInfo { public int Uid { get; set; } public string UName { get; ...

  3. AngularJS学习笔记(3)——通过Ajax获取JSON数据

    通过Ajax获取JSON数据 以我之前写的与用户交互的动态清单列表为例,使用JSON前todo.html代码如下: <!DOCTYPE html> <html ng-app=&quo ...

  4. angularjs之$ajax请求

    AngularJS不仅仅只有双向绑定等等功能,还有发送Ajax请求的Api. 效果图: 请求的文件(data.php): <?php $data = [ '股市下跌', '清明小长假结束', ' ...

  5. Drools5

    参考:https://wenku.baidu.com/view/a6516373f242336c1eb95e7c.html   (比较好的 但是是drl 原生的) 参考2:http://asialee ...

  6. eShopOnContainer 第一步

    运行结果截图: 操作流程: 1. git上clone 项目 windows版的docker并且安装成功,配置3核CPU,4G内存 vs 2017 (15.5)版本以上. 打开项目 eshopOnCon ...

  7. SpringBoot简单理解

    SpringBoot 一.特点:1.默认大于配置,不需要大量配置文件,没有web.xml,拥有可运行的Application类. 2.一般通过java代码配置,而尽量少使用xml配置. 3.maven ...

  8. Mybatis自动生成xml文件、dao接口、实体类

    Mybatis可以通过逆向工程,实现自动生成xml文件.dao接口.实体类 以下使用的是Intellij Idea进行自动生成 一.首先,要在pom.xml中导入插件,在<build>中加 ...

  9. 01-A-1: 计算

  10. leetcode 20 Valid Parentheses 有效的括号

    描述: 给定一些列括号,判断其有效性,即左括号有对应的有括号,括号种类只为小,中,大括号. 解决: 用栈. bool isValid(string s) { stack<char> st; ...