這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 背景 某一天,前端小餘同學和後端別問我小哥在做登錄業務介面對接,出於業務的特殊性和安全性的考慮,她和後端小哥約定“user”相關信息參數需要通過HTTP協議的header傳遞過來,利用HTTPS協議的頭部中的參數可以通過加密傳輸,從而保證 ...
這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
背景
某一天,前端小餘同學和後端別問我小哥在做登錄業務介面對接,出於業務的特殊性和安全性的考慮,她和後端小哥約定“user”相關信息參數需要通過HTTP協議的header傳遞過來,利用HTTPS協議的頭部中的參數可以通過加密傳輸,從而保證數據的安全性。
開發階段
確定技術方案之後,小餘同學在註冊發起請求函數的headers中新增user屬性:
export type User = { username: string; password: string; }; const handleRequest = async (userInfo: User, params: Object) => { try { await axios.post('/register-login-secure', params, { headers: { ...userInfo } }); } catch (e) { console.error(e); } };
這段代碼看起來是沒有任何問題,對嗎?
再看一下前端代碼的邏輯:
const Register = () => { const handleRequest = () => { // ... }; return ( <Form> <Form.Item field="username" label="用戶名"> <Input placeholder="請輸入用戶名" /> </Form.Item> <Form.Item field="password" label="密碼"> <Input.Password placeholder="請輸入密碼" /> </Form.Item> <Form.Item noStyle> <Button onClick={handleRequest} /> </Form.Item> </Form> ); };
整體看下來沒什麼問題,但是可以發現username是對用戶輸入沒有做任何校驗的,也就是說:無論用戶輸入什麼都可以存在資料庫的,這裡我們忽略xss攻擊。
由於這次的技術方案user信息是通過headers傳遞的,跟之前的傳參有一些出入以及在本地測試的時候,前端和後端在用戶名部分隨便輸入了一串英文字元串作為用戶名用於測試,發現沒問題於是就提測了。
測試階段
進入提測階段之後,測試同學把測試用例甩了過來:
場景一:註冊用戶名ashui,是否註冊成功
場景二:重覆註冊用戶名ashui,是否註冊成功
...
測試同學也順利的通過了所有測試用例,所以就上線了,線上驗收也沒什麼問題,所以大家都早早下班,各回各家,各找各媽。看到這裡,大家有發現什麼問題?如果有的話,請繼續往下看,看看猜想和後續遇到的問題是不是一直的。
事故階段
距離這次上線已經過去三天了,忽然小餘晚上三點半被P0加急電話吵醒,看到群里反饋有用戶無法註冊,小餘瞬間清醒打開電腦復現了一下,發現沒問題,群里大家復現都說沒問題,但運營同學跟客戶反覆溝通後,發現客戶確實無法註冊,於是小餘就去sentry監控查看了一下,忽然發現了之前從來沒有遇到的報錯:
Failed to read the 'headers' property from 'RequestInit': String contains non ISO-8859-1 code point.
小餘從這個報錯中窺探到一點信息是headers,程式員天生的直覺告訴她可能跟這次上線的技術方案有關,所以她去看了一下HTTP
協議的文檔.
解決階段
文檔裡面有這樣一段話:
By default, message header parameters in HTTP ([RFC2616]) messages can not carry characters outside the ISO-8859-1 character set ([ISO-8859-1]). RFC 2231 ([RFC2231]) defines an escaping mechanism for use in MIME headers. This document specifies a profile of that encoding for use in HTTP.
翻譯過來就是HTTP headers
中不能包含ISO-8859-1以外的字元集。小餘恍然大悟,用戶輸入的是中文的名字,所以趕緊試了一下,發現果然是這個問題,於是跟產品確定用戶名的用戶輸入的規範,以及跟後端小哥修改技術方案。
什麼是ISO-8859-1字元集
用於表示文本字元的編碼方案。它是國際標準化組織(ISO)制定的字元集之一,於1987年發佈。
ISO-8859-1 字元集包含了來自拉丁字母表的字元,主要用於表示西歐語言,如英語、法語、德語、西班牙語等。它是一個單位元組字元集(Single-Byte Character Set,SBCS),其中的每個字元都可以用一個位元組(8位)進行表示。ISO-8859-1 字元集共定義了256個字元,編號從0到255。
ISO-8859-1 字元集的編碼方案被廣泛應用於電腦系統和互聯網中的文本傳輸和存儲。在該字元集中,ASCII 字元(0-127)與 ASCII 字元集相同,因此 ISO-8859-1 是 ASCII 的一個超集。此外,ISO-8859-1 還包括了其他特定於歐洲語言的字元,如重音符號、希臘字母、貨幣符號等。
例如,ISO-8859-1 中的一些常見字元包括:
- 字母:A-Z、a-z
- 數字:0-9
- 標點符號:. , ; : ! ? ' " ( ) [ ] { } < > | / \ - + * = # @ $ % & _
- 特殊字元:© ® ° µ Æ æ Ø ø Å å
ISO-8859-1 字元集的編碼方案被廣泛支持,包括在操作系統、編程語言、文本編輯器、瀏覽器等軟體和工具中。然而,它僅適用於西歐語言,對於其他非西歐語言的字元,如中文、日文、韓文等,ISO-8859-1 並不適用。對於這些語言,通常使用其他字元集和編碼方案,如 UTF-8、UTF-16 等。
需要註意的是,ISO-8859-1 字元集與 Unicode 字元集是不同的概念。Unicode 是一種字元編碼標準,旨在為世界上所有的字元提供唯一的標識符,而 ISO-8859-1 是其中的一種字元集,只覆蓋了一部分字元。
後續
經過這次事故之後,小餘也加強了對HTTP新的理解,在HTTP協議中headers是需要遵循ISO-8859-1字元集規範,也為後續小餘成長做了一個警示。