BASE64编码乱码问题的浅层分析与解释
本文由作者朱臻授权网易云社区发布。
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编码乱码问题的浅层分析与解释的更多相关文章
- Tensorflow MNIST浅层神经网络的解释和答复
本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/51416540 看到之前的一篇博文:深入 ...
- 浅谈Base64编码
浅谈Base64编码 我打赌当你见到Base64这个词的时候你会觉得在哪里见过,因为在你能够上网看到这篇文章的时候你已经在后台使用它了.如果您对二进制数有所了解,你就可以开始读它了. 打开一封Emai ...
- 浅谈Base64编码算法
一.什么是编码解码 编码:利用特定的算法,对原始内容进行处理,生成运算后的内容,形成另一种数据的表现形式,可以根据算法,再还原回来,这种操作称之为编码. 解码:利用编码使用的算法的逆运算,对经过编码的 ...
- BASE64编码原理分析脚本实现及逆向案例
在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理你又了解多少?今天小编带大家了解一下Base64编码原理分析脚本实现及逆向案例的相关内容. 01编码由来 数 ...
- Base64编码原理分析
Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,在了解Base64编码之前,先了解几个基本概念:位.字节. 位:"位(bit)"是计算机中最小的数据单位.每一位 ...
- java base64编码 加密和解密(切记注意乱码问题)
BASE64 编码是一种常用的字符编码,在很多地方都会用到.JDK 中提供了非常方便的 BASE64Encoder 和 BASE64Decoder,用它们可以非常方便的完成基于 BASE64 的编码和 ...
- 一篇文章彻底弄懂Base64编码原理
在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理又了解多少?今天这篇博文带领大家了解一下Base64的底层实现. Base64的由来 目前Base64已经成为网 ...
- Delphi 读取 c# webservice XML的base64编码图片字符串转化图片并显示
Delphi 读取 c# webservice XML的base64编码图片字符串转化图片并显示 在 开发中遇到应用c#及asp.net的在的webservice 保存图片并以xml文件形式现实出来 ...
- 一篇文章彻底弄懂Base64编码原理(转载)
在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理又了解多少?今天这篇博文带领大家了解一下Base64的底层实现. Base64的由来 目前Base64已经成为网 ...
随机推荐
- 2_bootstrap的环境搭建
2.bootstrap环境搭建 2.1.下载资源 中文官网地址:http://d.bootcss.com/bootstrap-3.3.5.zip http://www.bootcss.com 2.2. ...
- React-Todos
最近学完React的最基本概念,闲下来的时候就自己写了一个Todo-List的小应用.这里做个简略的说明,给想好好学React的新手看. React-Todo 学习前提 这里我用了webpackb做了 ...
- OpenCL 使用函数 clCreateProgramWithBinary 来创建程序
▶ 函数 clCreateProgramWithSource 接收 OpenCL 代码(设备无关)来创建程序,而函数 clCreateProgramWithBinary 接收已经经过函数 clBuil ...
- WPF 出现“调用线程无法访问此对象,因为另一个线程拥有该对象”
引起这种错误多半是由于在非UI线程刷新界面,解决此问题可以使用Dispatcher this.Dispatcher.Invoke(new Action(() => { UpdateUI(stri ...
- joda-time的使用
值得一提的是该功能被整合到Java 8 中 ,被称为java8 新特新之一 .这意味着不用到包 <!-- 时间操作组件 --> <dependency> ...
- c# 数据拼接成键值对格式
public static object FindLayoutTypes() { //地鼓.地裂.墙裂.井水.泉水 var sb = new StringBuilder(); sb.Append(ge ...
- 迷你MVVM框架 avalonjs 0.9发布
本版本最大的改进是引进了ms-with绑定,现在可轻松遍历对象了. 改进列表如下: 重新使用082的scanNodes方法,因为有关旧式IE下UI渲染锁死的问题已经解决了. 优化each绑定与Coll ...
- react-native 组件的导入、导出
一.前言背景: 学习react native的关键在于组件,依靠组件的拼接达到想要的效果,由此可见,组件就像一块块功能各异的零件,最终搭建出我们想要的效果. 今天我们就从组件的导入.导出开始 下面是我 ...
- leetcode 14 最长公共前缀
描述: 给个字符串vector,求最长公共前缀. 解决: 直接取第一个字符串作为最长公共前缀,将其每个字符遍历过一次.设最长字符实际为k,共n个元素,则复杂度O(nk) string longestC ...
- Qt的安装和使用中的常见问题(详细版)
对于太长不看的朋友,可参考Qt的安装和使用中的常见问题(简略版). 目录 1.引入 2.Qt简介 3.Qt版本 3.1 查看安装的Qt版本 3.2 查看当前项目使用的Qt版本 3.3 查看当前项目使用 ...