当前位置: 首页 > 科技观察

前端开发字符编码详解

时间:2023-03-15 18:26:03 科技观察

在前端开发的过程中,你会接触到各种编码,比较常见的有UTF-8和HTML实体编码,但是web前端的世界-end不止这两种编码,编码编码的选择也会造成一定的问题,比如前后端开发过程中不同编码的兼容性,多编码可能导致的XSS漏洞字节编码等。因此,本文旨在更好地理解前端开发领域涉及的字符编码,避免开发中可能存在的交互和被忽视的漏洞。URL编码我曾经在URL编码解码与base64一文中描述了URL编码中的三组函数,并比较了这三组函数与base64编码的关系。这是一个简短的解释。escape/unescape函数对宽字符进行unicode编码,对code值进行16进制编码,所以使用escape对汉字进行编码会得到"\uxxxx"形式;用于宽字符的encodeURI/decodeURI、encodeURIComponent/decodeURIComponent函数段编码不同于转义。首先对宽字节字符进行UTF-8编码,然后对编码结果进行“%”替换,得到结果。以上都是针对宽字节字符的。对于更高编码的ASCII字符,以上三组函数的安全字符范围也有所不同,具体可以上文详细了解。Base64编码Base64编码通常用于前端对图片和图标的编码。它将每3个八位字节分成4组6位字节,每个字节的高位补零,组成4个8。可见base64编码是可逆的。大多数浏览器都提供了ASCII字符的base64编码函数,即window.btoa()。该函数不能对宽字节进行base64编码。如果是中文编码,需要先转成UTF-8编码,再进行base64编码。functionunicodeToBase64(s){returnwindow.btoa(unescape(encodeURIComponent(s)))}通过encodeURIComponent对宽字节字符进行编码,是一种“%xx”形式的编码。与UTF8编码唯一不同的是前缀(这是由规范RFC3986确定的,将非ASC字符以某种形式编码,转换为十六进制,在字节前加“%”)。因此,可以通过unescape(encodeURIComponent(s))将其转换为UTF8字节。当然你也可以自己写一个转换函数,按照一定的规则作为UTF-8编码的字节,如下例:```unescape(encodeURIComponent("China"))//result:"????"encodeURIComponent("China")//结果:"%E4%B8%AD%E5%9B%BD"console.log("\u00E4\u00B8\u00AD\u00E5\u009B\u00BD")//结果:"?????"```通过简单的replace函数,就可以完成URL编码到UTF8编码的转换,进而完成宽字节字符到base64编码的转换。通过这个功能,我们手动生成一些数据URI形式的内容,只需要指定MIME类型和编码方式就可以实现文本转换,比如下面的代码:```abc//编码前:测试```前端UTF8编码和后端-endGBKencodingCompatible现在的前端无论是html、js还是css,大部分都是使用UTF8进行编码,而后端由于历史原因多使用GBK或者GB2312进行解码,所以URL编码后的字符串通过前端通过参数无法直接在后台进行解码,为了更好的兼容性,前端可以进行两次URL编码,即encodeURIComponent(encodeURIComponent("China")),这样后台接收到参数后,end先用GBK或者GB2312解码,再用UTF8编码UTF8解码就可以了。两种编码主要是利用“ASC字符编码不变GBK或GB2312”这一特性来完成的,技巧性十足。HTML实体编码和十六进制编码实体编码是针对HTML中的保留字符,如“<>”等。实体编码有两种形式,&entityname;或者&entity_number;,因为浏览器对&entityname;的兼容性不同,所以最好使用entitynumber编码。十六进制编码,顾名思义,就是将ASC字符对应的编码值进行十六进制或十进制编码,转换成&#x;的形式。(十六进制)或&#D;(十进制)。单独没有特别强调实体编码。之所以单独列为一章,是为了强调这两种编码的关系和js代码的范围。')">cccc

')">cccc