問題的發(fā)現(xiàn)和原因:
我維護(hù)的一款 app 最近出現(xiàn)了一個(gè)問題,經(jīng)過我尋找問題后,發(fā)現(xiàn)這么一個(gè)現(xiàn)象。
有時(shí)候用戶用的 WiFi 的延遲特別高,以至于延遲超出了我設(shè)定網(wǎng)絡(luò)請求的超時(shí)時(shí)間。
此時(shí),app 會(huì)顯示網(wǎng)絡(luò)問題,提示用戶再次點(diǎn)擊按鈕發(fā)送網(wǎng)絡(luò)請求,然后用戶也確實(shí)按照提示再次點(diǎn)擊了按鈕。
然后由于網(wǎng)絡(luò)神奇的延遲,服務(wù)器很短時(shí)間內(nèi)收到了兩個(gè)包 。因?yàn)檫@個(gè)請求很重要,所以服務(wù)器對這個(gè)請求做了防包重放攻擊的措施,對于第二個(gè)包直接返回錯(cuò)誤。
然后我寫 app 的時(shí)候,完全沒有想到弱網(wǎng)絡(luò)情況下會(huì)導(dǎo)致“人為的重放攻擊”。所以我對于這個(gè)錯(cuò)誤的處理就比較激進(jìn)。
后來用戶使用 app 的時(shí)候發(fā)生了上述的情況,我才發(fā)現(xiàn)這里存在問題。
目前使用的解決方法:
知道了問題的原因,解決起來就有方向了。
在服務(wù)器端:
對這個(gè)包的請求做hash,對于相同的請求包,只響應(yīng)第一個(gè)請求,后續(xù)的相同請求不響應(yīng)。
保存所有的請求包的 hash 成本很高,我覺得保存最近 5-10min 的hash就行了。
在移動(dòng)端:
發(fā)送重要請求前先向服務(wù)器發(fā)一個(gè)無關(guān)緊要的請求“探探路”。要是請求正常,下一步發(fā)送重要請求。否則,請用戶更換網(wǎng)絡(luò)環(huán)境再重試。
以上這兩個(gè)解決方法是我根據(jù)我正在維護(hù)的 app 的現(xiàn)狀腦洞出來的。
第二種是我目前正在使用的。
當(dāng)然啦,這個(gè)問題還是在設(shè)計(jì)階段就考慮到比較好。等發(fā)現(xiàn)了問題再修補(bǔ)就很難受了。
歡迎交流~