摘要:當后端將數據取出再傳給前端時,發生了編碼混亂的問題。這樣的編碼錯誤問題導致數據上的,會造成不良的用戶體驗。但是,不幸的是,各方對該編碼的規則是不同的,這也造成亂碼的隱患。
本文由作者朱臻授權網易云社區發布。
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等。 本文只是分享個人處理該問題的經驗,如遇錯誤之處,請各位批評指正,也歡迎各位探討交流。
更多網易技術、產品、運營經驗分享請訪問網易云社區。
文章來源: 網易云社區
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/25321.html
摘要:字符集編碼就是對字符根據不同字符集中對應的格式進行編碼解碼,這個大家都好理解。下面詳細說說,以編碼解碼和編碼解碼為例。 《來自羅志曉的筆記:http://note.youdao.com/notesh...》我們平時老說的編碼解碼,很多人都只知道 字符集編碼解碼。其實除了字符集編碼解碼,常見的還有另一類,如 Url編碼解碼、Base64編碼解碼。這兩類編碼的原理是完全不一樣的,如果沒有了...
摘要:注意點如果所示,上面說到的編碼解碼方法并不支持中文,因為它們只支持編碼。轉換編碼中文進行轉碼之后在編碼。最優方案在某些情況下,用了上面的方法也會出現中文亂碼的情況,如獲取到的音樂歌詞解析出來的歌詞等。 為什么要編碼 簡單粗暴的解釋就是為了數據的安全性。 編碼/解碼常用方法(僅針對Base64) 編碼 我們一般使用 window.btoa() 對原始數據進行編碼。 解碼 我們一般使用 w...
摘要:對于第二種存儲方式,我們前端需要將其二進制流交由對象處理,然后通過的生成臨時賦值給屬性來顯示。當后端返回特定的圖片二進制流的時候,就像我第一里的情景再現說的,前端用容器接收。 前言 作為前端工程師 de 我們,日常少不了會跟圖片打交道。在各大電商平臺工作的前端工程師們,感受可能會更加的明顯。 以下是我之前跟圖片打交道踩到的坑,跟大家分享一下經驗。 一、情景再現 用postman請求接口...
摘要:對于第二種存儲方式,我們前端需要將其二進制流交由對象處理,然后通過的生成臨時賦值給屬性來顯示。當后端返回特定的圖片二進制流的時候,就像我第一里的情景再現說的,前端用容器接收。 前言 作為前端工程師 de 我們,日常少不了會跟圖片打交道。在各大電商平臺工作的前端工程師們,感受可能會更加的明顯。 以下是我之前跟圖片打交道踩到的坑,跟大家分享一下經驗。 一、情景再現 用postman請求接口...
閱讀 2077·2023-04-25 21:11
閱讀 2966·2021-09-30 09:47
閱讀 2277·2021-09-24 09:48
閱讀 4434·2021-08-23 09:43
閱讀 899·2019-08-30 15:54
閱讀 566·2019-08-28 18:01
閱讀 1402·2019-08-27 10:55
閱讀 591·2019-08-27 10:55